1 Read and Merge

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Clean & Merge
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Data_STAI <- 
  Data_STAI %>% 
  dplyr::filter(!is.na(ID)) %>%                                                                # no ID, no data
  dplyr::filter(rowSums(is.na(.)) < 2) %>%                                                     # filter out rows (no more than 1 NA on row)
  mutate(ID = stringr::str_replace(ID, "\\s", "|")) %>%                                        # replace first whitespace with | and use it to separate
  tidyr::separate(ID, into = c("ID", "Experim"), sep = "\\|") %>%                              # separate on only first whitespace that was replaced
  dplyr::select(-Experim)

Data_BDI <- 
  Data_BDI %>% 
  dplyr::filter(!is.na(ID)) %>%                                                                # no ID, no data
  dplyr::filter(rowSums(is.na(.)) < 1) %>%                                                     # filter out rows (not 1 NA)
  mutate(ID = stringr::str_replace(ID, "\\s", "|")) %>%                                        # replace first whitespace with | and use it to separate
  tidyr::separate(ID, into = c("ID", "Experim"), sep = "\\|") %>%                              # separate on only first whitespace that was replaced
  dplyr::select(-Experim)

Data_Neo <- 
  Data_Neo %>% 
  dplyr::filter(!is.na(ID)) %>%                                                                # no ID, no data
  dplyr::filter(rowSums(is.na(.)) < 6) %>%                                                     # filter out rows (no more than 5 NA on row)
  mutate(ID = stringr::str_replace(ID, "\\s", "|")) %>%                                        # replace first whitespace with | and use it to separate
  tidyr::separate(ID, into = c("ID", "Experim"), sep = "\\|") %>%                              # separate on only first whitespace that was replaced
  dplyr::select(-Experim)

Data_psih <- 
  Data_psih %>% 
  dplyr::filter(!is.na(ID)) %>%                                                                # no ID, no data
  dplyr::filter(rowSums(is.na(.)) < 8) %>%                                                     # filter out rows (no more than 7 NA on row)
  tidyr::separate(Conditia,  c("Nr_zi", "Conditia"), "\\s+") %>%                               # split on white space
  mutate(ID = stringr::str_replace(ID, "\\s", "|")) %>%                                        # replace first whitespace with | and use it to separate
  tidyr::separate(ID, into = c("ID", "Experim"), sep = "\\|") %>%                              # separate on only first whitespace that was replaced
  dplyr::rename("Nume" = Nume_Prenume) %>% 
  dplyr::select(-Experim)

Data_OXT <-   
  Data_OXT %>% 
  tidyr::separate(ID,  c("ID", "Ziua", "Nr_zi", "Proba"), "\\s+") %>%                          # split on white space
  select(ID, Nr_zi, Proba, OXT) %>%
  tidyr::separate(ID, into = c("ID", "Experim"), sep = "\\/") %>%                              # separate on /
  dplyr::select(-Experim) %>% 
  dplyr::rename("PrePost" = Proba) %>% 
  mutate(PrePost = forcats::fct_recode(PrePost, "Pre" = "A", "Post" = "B")) %>%                # Proba A = Pre, B = Post on same day
  spread(key = PrePost, value = OXT) %>%
  dplyr::rename_at(vars(Pre, Post), ~ c("OXT_Pre", "OXT_Post"))


Data_merged <- dplyr::left_join(Data_psih, Data_OXT, by = c("ID", "Nr_zi"))                 # ID 40, 59 are incomplete in OXT -- dplyr::full_join


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Make Wide Dataframe of merged
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Check if ids have > 1 row of data (empty ID have only 1 row; thei have only 1 Condition) 
# Careful! This function modfies the datasets in the global envinronment
delete_empty_id <- function(df){
  list_empty_id <- 
    df %>%
    dplyr::group_by(ID) %>%
    dplyr::summarise(row_count = n()) %>%
    dplyr::rename("empty_id" = ID) %>%
    mutate(delete_id = if_else(row_count < 2, TRUE, FALSE)) %>%
    filter(delete_id == TRUE)
  
  df_modif <- 
    df %>%
    filter(!ID %in% list_empty_id$empty_id)
  
  if(!identical(df, df_modif)){
    df <- deparse(substitute(df))
    cat("Deleting from ", print(as.name(df))); print(list_empty_id)                    # print out which ids are deleted from which dataset
    assign(df, df_modif, envir = globalenv())                                          # assign modified df to original dataset from Global
  }else cat("No empty datasets. Nothing to delete")
}
delete_empty_id(Data_merged) 

Data_merged Deleting from Data_merged

# Dataframe for regular analyses
Data_merged_wide <-
  Data_merged %>%
  select(-c(Varsta, Gen)) %>%            # exclude Gen, Varsta: merge after because it interferes with spread()
  gather("variable", "value", c(Data, Nr_zi, Vas_Stres_Pre:OXT_Post), -c(1:2)) %>%       # Conditia needs to be outside
  unite("united_var", c(variable, Conditia), sep = "_") %>%
  spread(united_var, value) %>%
  mutate_at(vars(5:22), list(~as.numeric(as.character(.))))

# sum(is.na(Data_merged[, 6:15])) == sum(is.na(Data_merged_wide[, 5:22]))    # check if nr of NA is the same after melt


# Full Wide Dataframe  (HERE We APPLY EXCLUSION CRITERIA) 
Data_merged_wide_all <- 
  Data_merged[, c("ID", "Nume", "Varsta", "Gen")] %>%                        # need to add these back, but just the main unduplicated row
  dplyr::distinct(ID, .keep_all = TRUE) %>%
    dplyr::left_join(., Data_merged_wide, by = "ID") %>%
    dplyr::rename("Nume" = Nume.x) %>%
    dplyr::select(-Nume.y) %>% 
    dplyr::left_join(., Data_BDI, by = "ID") %>%
    dplyr::left_join(., Data_STAI, by = "ID") %>%
    dplyr::left_join(., Data_Neo, by = "ID") %>%
    mutate_at(vars(23:60), list(~as.numeric(as.character(.)))) %>%
    mutate(Varsta = as.numeric(as.character(Varsta))) %>% 
    filter(!ID %in% c(19, 43)) %>%           # 55 subs remain after this
    filter(Varsta < 40) %>%                  # 53 subs remain after this
    filter(ScorBDI < 30) %>%                 # 50 subs remain after this
    dplyr::arrange(ID)


# Full Long Dataframe
vars_OglEcran <- grep("OGL|ECRAN", colnames(Data_merged_wide_all))

Data_merged_long_all <-
  Data_merged_wide_all %>%
  gather(variable, value, vars_OglEcran, -c(ID)) %>%                                      # gather Data and Nr_zi as these are OglEcran level
  tidyr::separate(variable,  c("variable", "OglEcran"), "_(?=[^_]+$)") %>%                # split only on last "_"
  spread(variable, value) %>% 
  rename_at(vars(vars_OglEcran), list(~stringr::str_remove_all(., c("_OGL|_ECRAN")))) %>%          
  arrange(ID)

vars_PrePost <- grep("Pre|Post", colnames(Data_merged_long_all))

Data_merged_long_all <-
  Data_merged_long_all %>%
  pivot_longer(vars_PrePost, names_to = c(".value","PrePost"), names_pattern = "(.*)_(.*)") %>%     # magic     
  mutate_at(vars(48:50), list(~as.numeric(as.character(.)))) %>%
  arrange(ID)


# Females and Males Dataframes
Data_fem <- 
  Data_merged_wide_all %>%
  filter(Gen == "f")
Data_masc <- 
  Data_merged_wide_all %>%
  filter(Gen == "m")

# Difference Scores Dataframe
Data_difscores <-
  Data_merged_wide_all %>%
  mutate(Diff_OXT_OGL = OXT_Post_OGL - OXT_Pre_OGL,
         Diff_OXT_ECRAN = OXT_Post_ECRAN - OXT_Pre_ECRAN,
         Diff_Vas_Stres_OGL = Vas_Stres_Post_OGL - Vas_Stres_Pre_OGL,
         Diff_Vas_Stres_ECRAN = Vas_Stres_Post_ECRAN - Vas_Stres_Pre_ECRAN, 
         Diff_Vas_Bine_OGL = Vas_Bine_Post_OGL - Vas_Bine_Pre_OGL,
         Diff_Vas_Bine_ECRAN = Vas_Bine_Post_ECRAN - Vas_Bine_Pre_ECRAN,
         Diff_IOS_OGL = IOS_Post_OGL - IOS_Pre_OGL,
         Diff_IOS_ECRAN = IOS_Post_ECRAN - IOS_Pre_ECRAN
  ) 

1.1 Dataset - Long Format

1.2 Dataset - Wide Format

2 Descriptives

2.1 Descriptives - Gen Varsta


   f    m 
0.54 0.46 
cannot compute exact p-value with ties

 Descriptive statistics by group 
group: f
------------------------------------------------------------------------------------------------------------ 
group: m

2.2 Plots

2.3 t test Varsta by Gen

Varsta by Gen
var Gen missing n M SD SE min max range median mode skew kurtosis
Varsta f 0 27 25.44 5.49 1.06 20 37 17 24 20 0.78 2.30
Varsta m 0 23 26.00 4.67 0.97 20 39 19 25 23 0.81 3.62

3 Define Functions

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define Function for mining correlations
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Function for p-value significance -- both for func_ancova_multibox(), Get_Top_Relationships() and Correlations_With_One()
stars_signif <- function(pval) {
  stars = "ns"
  if(pval <= 0.001)
    stars = "***"
  if(pval > 0.001 & pval <= 0.01)
    stars = "**"
  if(pval > 0.01 & pval <= 0.05)
    stars = "*"
  if(pval > 0.05 & pval <= 0.1)
    stars = "."
  stars
}

## Function that returns correlations of all variables in descending order.
# Arg for threshold with default at .3 will keep only correlantions above .3 and below -.3. Also has threshhold for p-value. 
Get_Top_Relationships <- function(data_set, 
                                  correlation_abs_threshold=0.3,
                                  pvalue_threshold=0.05) {
  require(psych)
  require(dplyr)
  feature_names <- names(data_set)
  # strip var names to index for pair-wise identification
  names(data_set) <- seq(1:ncol(data_set))
  # calculate correlation and significance numbers
  cor_data_df <- psych::corr.test(data_set)
  # apply var names to correlation matrix over index
  rownames(cor_data_df$r) <- feature_names
  colnames(cor_data_df$r) <- feature_names
  # top cor and sig
  relationships_set <- cor_data_df$ci[,c('r','p')]
  # apply var names to data over index pairs
  relationships_set$feature_1 <- feature_names[as.numeric(sapply(strsplit(rownames(relationships_set), "-"), `[`, 1))]
  relationships_set$feature_2 <- feature_names[as.numeric(
    sapply(strsplit(rownames(relationships_set), "-"), `[`, 2))]
  relationships_set <- dplyr::select(relationships_set, feature_1, feature_2, r, p) %>% dplyr::rename(correlation = r, p.value = p)
  # return only the most insteresting relationships
  return(filter(relationships_set, abs(correlation) > correlation_abs_threshold &
                  p.value < pvalue_threshold) %>% 
        arrange(p.value) %>%
        mutate(p.signif = sapply(p.value, function(x) stars_signif(x))))
}

## Function that returns all correlation between numeric variables and one specific variable
Correlations_With_One <- function(data_set,
                            variable,
                            correlation_abs_threshold=0.3,
                            pvalue_threshold=0.05) {
  require(psych)
  require(dplyr)
  # use all numeric columns only
  numeric_cols <- unlist(lapply(data_set, is.numeric))
  data_set <- data_set[, numeric_cols]                               
  # calculate correlation and significance numbers
  cor_data_df <- psych::corr.test(data_set[, names(data_set) != variable], data_set[, variable], minlength = 20, adjust="none")
  # top cor and sig
  relationships_set <- as.data.frame(cbind(cor_data_df$r, cor_data_df$p))     # same as  cor_data_df$ci[,c('r','p')]
  relationships_set <- tibble::rownames_to_column(relationships_set, "Variable")   # relationships_set$Variable <- rownames(relationships_set)
  colnames(relationships_set) <- c("Variable", "correlation", "p.value")
  # return only the most insteresting relationships
  cat("#### Correlations with ", variable, "\n")
  return(filter(relationships_set, abs(correlation) > correlation_abs_threshold &
                  p.value < pvalue_threshold) %>% 
           arrange(p.value) %>%
           mutate(p.signif = sapply(p.value, function(x) stars_signif(x)))) %>%
           tibble::as.tibble()
}  


## Function for ploting correlation data frames resulting from Get_Top_Relationships and Correlations_With_One()
func_dotplot_cor <- function(df){                                        # https://www.r-pkg.org/pkg/ggpubr
  dotplotcor_scale_fill <- function(...){                                # Fix colors to signif factor levels even if missing
    ggplot2:::manual_scale(                                   
      'color', 
      values = setNames(
        c("darkgreen", "green3", "lawngreen", "yellow", "red"), 
        c("***", "**", "*", ".", "ns")), 
      ...
    )
  }                                           
  
  dtoplot_theme <- 
    ggpubr::theme_pubr() +
    theme(axis.text.y = element_text(size = 10))
  
  if(!"Variable" %in% colnames(df)){                                             # in oder to work for both Get_Top_Relationships and Correlations_With_One()
  df <- 
    df %>%                                            
      unite(cor_between, c("feature_1", "feature_2"), sep = " X ")               # unite 2 columns to x name from plot
  }else df <- df %>% dplyr::rename(cor_between = Variable)                       # change Variable to x name from plot
  
  df %>%
    ggpubr::ggdotchart(x = "cor_between", y = "correlation",
                       color = "p.signif",                                       # Color by sig
                       #   palette = c("#00AFBB", "#E7B800", "#FC4E07"),         # Custom color palette
                       sorting = "descending",                                   # Sort value in descending order
                       add = "segments",                                         # Add segments from y = 0 to dots
                       add.params = list(color = "lightgray", size = 2),         # Change segment color and size
                       group = "p.signif",                                       # Order by groups
                       dot.size = 8,                                             # Large dot size
                       xlab = "",
                       rotate = TRUE,                                            # Rotate vertically
                       label = round(.$correlation, 1),                          # Add mpg values as dot labels
                       font.label = list(color = "white", size = 9, 
                                         vjust = 0.5),                           # Adjust label parameters
                       ggtheme = dtoplot_theme) +                                # ggplot2 theme
    dotplotcor_scale_fill() +                                            # Fix colors to signif factor levels even if missing
    geom_hline(yintercept = 0, linetype = 2, color = "lightgray")
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define Function for Pre-Post Plots, t Change and ANCOVA Post
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Func t test si boxplot simplu
func_t_box <- function(df, ind, pre_var, post_var){
  df_modif <-
    df %>%
    select(ind, pre_var, post_var) %>% 
    tidyr::drop_na() %>%
    gather(pre_var, post_var, key = "Cond", value = "value") %>% 
    mutate_at(vars(c(1, 2)), list(~as.factor(.))) %>% 
    mutate(Cond = factor(Cond, levels = c(pre_var, post_var))) 
  
  stat_comp <- ggpubr::compare_means(value ~ Cond, data = df_modif, method = "t.test", paired = TRUE)
  
  stat_comp2 <-
    df_modif %>% 
    do(tidy(t.test(.$value ~ .$Cond,
                   paired = TRUE,
                   data=.)))
  
  plot <- 
    ggpubr::ggpaired(df_modif, x = "Cond", y = "value", id = ind, 
                     color = "Cond", line.color = "gray", line.size = 0.4,
                     palette = c("#00AFBB", "#FC4E07"), legend = "none") +
      stat_summary(fun.data = mean_se,  colour = "darkred") +
      ggpubr::stat_compare_means(method = "t.test", paired = TRUE, label.x = as.numeric(df_modif$Cond)-0.4, label.y = max(df_modif$value)+0.5) + 
      ggpubr::stat_compare_means(method = "t.test", paired = TRUE, label = "p.signif", comparisons = list(c(pre_var, post_var)))
  
  cat(paste0("#### ", pre_var, " ", post_var, "\n", "\n"))
  print(stat_comp)
  print(stat_comp2)
  print(plot)
}


func_ancova_multibox <- function(df, ind, pre_var_c1, post_var_c1, pre_var_c2, post_var_c2){
  
  diff_score_c1 <- paste0(post_var_c1, " - ", pre_var_c1)
  diff_score_c2 <- paste0(post_var_c2, " - ", pre_var_c2)
  
  ## Plots and p-values for t tests
  df_modif <-
    df %>%
    select(ind, pre_var_c1, post_var_c1, pre_var_c2, post_var_c2) %>% 
    tidyr::drop_na() %>%
    gather(pre_var_c1, post_var_c1, pre_var_c2, post_var_c2, key = "Cond", value = "value") %>% 
    mutate_at(vars(c(1, 2)), list(~as.factor(.))) %>% 
    mutate(Cond = factor(Cond, levels = c(pre_var_c1, post_var_c1, pre_var_c2, post_var_c2))) 
  
  stat_comp <- ggpubr::compare_means(value ~ Cond, data = df_modif, method = "t.test", paired = TRUE, p.adjust.method = "holm")
  
  plot <-
    ggpubr::ggpaired(df_modif, x = "Cond", y = "value", id = ind, 
                     color = "Cond", line.color = "gray", line.size = 0.4,
                     palette = c("#00AFBB", "#FC4E07", "#00AFBB", "#FC4E07"), legend = "none") +
    stat_summary(fun.data = mean_se,  colour = "darkred") +
    ggpubr::stat_compare_means(method = "t.test", paired = TRUE, label = "p.signif", 
                               label.y = c(max(df_modif$value) + 0.1*IQR(df_modif$value),
                                           max(df_modif$value) + 0.1*IQR(df_modif$value),
                                           seq(max(df_modif$value) + 0.3*IQR(df_modif$value), 
                                               max(df_modif$value) + 0.9*IQR(df_modif$value), length.out = 4)),  
                               comparisons = list(c(pre_var_c1, post_var_c1),
                                                  c(pre_var_c2, post_var_c2),
                                                  c(post_var_c1, pre_var_c2),
                                                  c(pre_var_c1, pre_var_c2),
                                                  c(post_var_c1, post_var_c2),
                                                  c(pre_var_c1, post_var_c2)))
  
  ## For ttestChange or ANCOVAChange - we do ttestChange (Post-Pre) here, but it isnt very important
  df_modif2 <-                                 
    df %>%
    select(ind, pre_var_c1, post_var_c1, pre_var_c2, post_var_c2) %>%
    tidyr::drop_na() 
  df_modif2[diff_score_c1] <- df_modif2[, post_var_c1] - df_modif2[, pre_var_c1]
  df_modif2[diff_score_c2] <- df_modif2[, post_var_c2] - df_modif2[, pre_var_c2]
  
  tChange <- t.test(df_modif2[, diff_score_c1], df_modif2[, diff_score_c2], paired = TRUE)
  
  ## For descriptives by 2 factors (PrePost and OglEcran)
  df_modif3 <-
    df %>%
    select(ind, pre_var_c1, post_var_c1, pre_var_c2, post_var_c2) %>%
    tidyr::drop_na() %>%
    gather(pre_var_c1, post_var_c1, pre_var_c2, post_var_c2, key = "Cond", value = "value") %>%
    mutate(PrePost = case_when(stringr::str_detect(.$"Cond", "pre|Pre") ~ "Pre",
                               stringr::str_detect(.$"Cond", "post|Post") ~ "Post",
                               TRUE ~ NA_character_),
           OglEcran = case_when(stringr::str_detect(.$"Cond", "ogl|OGL") ~ "OGL",
                              stringr::str_detect(.$"Cond", "ecran|ECRAN") ~ "ECRAN",
                              TRUE ~ NA_character_)) %>%
    mutate(PrePost = as.factor(PrePost),
           OglEcran = as.factor(OglEcran))
  
  ## For ANCOVAPost - this is what we use
  df_modif4 <-
    df_modif3 %>%
    select(-"Cond") %>%
    spread("PrePost", "value")
  
  ## Models (here we use ANCOVAPost)    # https://m-clark.github.io/docs/mixedModels/anovamixed.html#introduction
  full_ancovaPost <-                                          # this is better than using lm() and glht()
      jmv::ancova(
        formula = Post ~ Pre + OglEcran,
        data = df_modif4,
        homo = TRUE,
        ss = "3",                                                     
        postHoc = ~ OglEcran,
        postHocCorr = list("tukey"),
        effectSize = list("eta", "partEta")
      )
  
      # mod_ancovaPost <- lm(Post ~ Pre + OglEcran, data = df_modif4)            # this is a Covariate Second model
      # mod_ancovaPost_ss3 <- car::Anova(mod_ancovaPost, type = "III")         # Type III sums of squares; see Andy Fields 2012
      # postHocs <- multcomp::glht(mod_ancovaPost, linfct = multcomp::mcp(OglEcran = "Tukey"))  # differences between the adjusted means,
      # sum_postHocs <- summary(postHocs)                                               # use Tukey or Dunnett?s post hoc tests
      # conf_postHocs <- confint(postHocs)
  scatter <-                                                             # Check for homogeneity of regression slopes
    ggplot(df_modif4, aes(Pre, Post, colour = OglEcran)) +
    geom_point(aes(shape = OglEcran), size = 3) +
    geom_smooth(method = "lm", aes(fill = OglEcran), alpha = 0.1)
    
  
  ## Other Models that work for this date
  # mod_ancovaPost <- lm(post ~ pre + treat)      # exactly the same with aov(post ~ pre + treat)
  # summary(mod_ancovaPost)
  # 
  # mod_anovaRM <- aov(score ~ treat*time + Error(id), dflong)
  # summary(mod_anovaRM)
  # 
  # mod_lme <- lme4::lmer(score ~ treat*time + (1|id), data=dflong)
  # anova(lmeModel)
  
  ## Output
  print(plot)
  cat(paste0("#### ", pre_var_c1, " ", post_var_c1, " ", pre_var_c2, " ", post_var_c2, "\n", "\n"))
  
  cat("#### Descriptives")
  psych::describeBy(df_modif3[, "value"], list(df_modif3[, "PrePost"], df_modif3[, "OglEcran"]), mat = TRUE) %>% 
    as.tibble() %>%
    print()
  cat("\n")
  
  print(stat_comp)
  cat("\n")
  
  cat("#### t Change")
  tidy(tChange) %>% print()
  cat("\n")
  
  cat("#### ANCOVA Post")
  cat("\n")
  cat("##### Homogeneity test")
  print(tibble::as.tibble(full_ancovaPost$assump$homo))
  cat("##### ANCOVA output")
  print(tibble::as.tibble(full_ancovaPost$main))
  # tidy(mod_ancovaPost) %>% 
  #   mutate(p.signif = sapply(p.value, function(x) stars_signif(x))) %>% 
  #   print()
  # cat("\n")
  cat("##### Post Hoc")
  print(tibble::as.tibble(full_ancovaPost$postHoc[[1]]))
  # tidy(sum_postHocs) %>% 
  #   mutate(p.signif = sapply(p.value, function(x) stars_signif(x))) %>% 
  #   print()
  cat("\n")
  cat("##### Homogeneity of regression slopes")
  # subchunkify(plot(scatter), 5, 5)                       # THIS FUNC CRASHES PANDOC CONVERSION WITH ERROR 99 - DONT USE HERE
}

4 Analyses

4.1 Simple before-after analyses with t test

4.1.0.1 OXT_Pre_OGL OXT_Post_OGL

4.1.0.2 OXT_Pre_ECRAN OXT_Post_ECRAN

4.1.0.3 Vas_Stres_Pre_OGL Vas_Stres_Post_OGL

4.1.0.4 Vas_Stres_Pre_ECRAN Vas_Stres_Post_ECRAN

4.1.0.5 Vas_Bine_Pre_OGL Vas_Bine_Post_OGL

4.1.0.6 Vas_Bine_Pre_ECRAN Vas_Bine_Post_ECRAN

4.1.0.7 IOS_Pre_OGL IOS_Post_OGL

4.1.0.8 IOS_Pre_ECRAN IOS_Post_ECRAN

4.2 tChance and ANCOVAPost

4.2.0.1 OXT_Pre_OGL OXT_Post_OGL OXT_Pre_ECRAN OXT_Post_ECRAN

4.2.0.2 Descriptives

NA

4.2.0.3 t Change

4.2.0.4 ANCOVA Post

4.2.0.4.1 Homogeneity test
4.2.0.4.2 ANCOVA output
4.2.0.4.3 Post Hoc

4.2.0.5 Vas_Stres_Pre_OGL Vas_Stres_Post_OGL Vas_Stres_Pre_ECRAN Vas_Stres_Post_ECRAN

4.2.0.6 Descriptives

NA

4.2.0.7 t Change

4.2.0.8 ANCOVA Post

4.2.0.8.1 Homogeneity test
4.2.0.8.2 ANCOVA output
4.2.0.8.3 Post Hoc

4.2.0.9 Vas_Bine_Pre_OGL Vas_Bine_Post_OGL Vas_Bine_Pre_ECRAN Vas_Bine_Post_ECRAN

4.2.0.10 Descriptives

NA

4.2.0.11 t Change

4.2.0.12 ANCOVA Post

4.2.0.12.1 Homogeneity test
4.2.0.12.2 ANCOVA output
4.2.0.12.3 Post Hoc

4.2.0.13 IOS_Pre_OGL IOS_Post_OGL IOS_Pre_ECRAN IOS_Post_ECRAN

4.2.0.14 Descriptives

NA

4.2.0.15 t Change

4.2.0.16 ANCOVA Post

4.2.0.16.1 Homogeneity test
4.2.0.16.2 ANCOVA output
4.2.0.16.3 Post Hoc
4.2.0.16.4 Homogeneity of regression slopes

4.3 Simple before-after analyses with t test by Gender

4.3.1 Fem

4.3.1.1 OXT_Pre_OGL OXT_Post_OGL

4.3.1.2 OXT_Pre_ECRAN OXT_Post_ECRAN

4.3.1.3 Vas_Stres_Pre_OGL Vas_Stres_Post_OGL

4.3.1.4 Vas_Stres_Pre_ECRAN Vas_Stres_Post_ECRAN

4.3.1.5 Vas_Bine_Pre_OGL Vas_Bine_Post_OGL

4.3.1.6 Vas_Bine_Pre_ECRAN Vas_Bine_Post_ECRAN

4.3.1.7 IOS_Pre_OGL IOS_Post_OGL

4.3.1.8 IOS_Pre_ECRAN IOS_Post_ECRAN

4.3.2 Masc

4.3.2.1 OXT_Pre_OGL OXT_Post_OGL

4.3.2.2 OXT_Pre_ECRAN OXT_Post_ECRAN

4.3.2.3 Vas_Stres_Pre_OGL Vas_Stres_Post_OGL

4.3.2.4 Vas_Stres_Pre_ECRAN Vas_Stres_Post_ECRAN

4.3.2.5 Vas_Bine_Pre_OGL Vas_Bine_Post_OGL

4.3.2.6 Vas_Bine_Pre_ECRAN Vas_Bine_Post_ECRAN

4.3.2.7 IOS_Pre_OGL IOS_Post_OGL

4.3.2.8 IOS_Pre_ECRAN IOS_Post_ECRAN

4.4 tChance and ANCOVAPost by Gender

4.4.1 Fem

4.4.1.1 OXT_Pre_OGL OXT_Post_OGL OXT_Pre_ECRAN OXT_Post_ECRAN

4.4.1.2 Descriptives

NA

4.4.1.3 t Change

4.4.1.4 ANCOVA Post

4.4.1.4.1 Homogeneity test
4.4.1.4.2 ANCOVA output
4.4.1.4.3 Post Hoc

4.4.1.5 Vas_Stres_Pre_OGL Vas_Stres_Post_OGL Vas_Stres_Pre_ECRAN Vas_Stres_Post_ECRAN

4.4.1.6 Descriptives

NA

4.4.1.7 t Change

4.4.1.8 ANCOVA Post

4.4.1.8.1 Homogeneity test
4.4.1.8.2 ANCOVA output
4.4.1.8.3 Post Hoc

4.4.1.9 Vas_Bine_Pre_OGL Vas_Bine_Post_OGL Vas_Bine_Pre_ECRAN Vas_Bine_Post_ECRAN

4.4.1.10 Descriptives

NA

4.4.1.11 t Change

4.4.1.12 ANCOVA Post

4.4.1.12.1 Homogeneity test
4.4.1.12.2 ANCOVA output
4.4.1.12.3 Post Hoc

4.4.1.13 IOS_Pre_OGL IOS_Post_OGL IOS_Pre_ECRAN IOS_Post_ECRAN

4.4.1.14 Descriptives

NA

4.4.1.15 t Change

4.4.1.16 ANCOVA Post

4.4.1.16.1 Homogeneity test
4.4.1.16.2 ANCOVA output
4.4.1.16.3 Post Hoc
4.4.1.16.4 Homogeneity of regression slopes

4.4.2 Masc

4.4.2.1 OXT_Pre_OGL OXT_Post_OGL OXT_Pre_ECRAN OXT_Post_ECRAN

4.4.2.2 Descriptives

NA

4.4.2.3 t Change

4.4.2.4 ANCOVA Post

4.4.2.4.1 Homogeneity test
4.4.2.4.2 ANCOVA output
4.4.2.4.3 Post Hoc

4.4.2.5 Vas_Stres_Pre_OGL Vas_Stres_Post_OGL Vas_Stres_Pre_ECRAN Vas_Stres_Post_ECRAN

4.4.2.6 Descriptives

NA

4.4.2.7 t Change

4.4.2.8 ANCOVA Post

4.4.2.8.1 Homogeneity test
4.4.2.8.2 ANCOVA output
4.4.2.8.3 Post Hoc

4.4.2.9 Vas_Bine_Pre_OGL Vas_Bine_Post_OGL Vas_Bine_Pre_ECRAN Vas_Bine_Post_ECRAN

4.4.2.10 Descriptives

NA

4.4.2.11 t Change

4.4.2.12 ANCOVA Post

4.4.2.12.1 Homogeneity test
4.4.2.12.2 ANCOVA output
4.4.2.12.3 Post Hoc

4.4.2.13 IOS_Pre_OGL IOS_Post_OGL IOS_Pre_ECRAN IOS_Post_ECRAN

4.4.2.14 Descriptives

NA

4.4.2.15 t Change

4.4.2.16 ANCOVA Post

4.4.2.16.1 Homogeneity test
4.4.2.16.2 ANCOVA output
4.4.2.16.3 Post Hoc
4.4.2.16.4 Homogeneity of regression slopes

4.5 Not considering Cond (OglEcran) - Overall Pre-Post

4.5.0.1 OXT_Pre OXT_Post

4.5.0.2 Vas_Stres_Pre Vas_Stres_Post

4.5.0.3 Vas_Bine_Pre Vas_Bine_Post

4.5.0.4 IOS_Pre IOS_Post

4.6 Difference scores conditioned on Anxiety ?

Missing rows: 17, 26, 34, 43

Missing rows: 17, 26, 34, 43

Missing rows: 17, 26, 34, 43

Missing rows: 17, 26, 34, 43

4.7 Difference scores conditioned on Extraversion ?

## Define Function
func_moderation <- function(Data, dep, mod, pred){
  moderation <- 
    Data %>%
    medmod::mod(., dep = dep, mod = mod, pred = pred,
                ci = TRUE, estMethod = 'standard', test = TRUE, simpleSlopeEst = FALSE, simpleSlopePlot = TRUE)
  
  cat(paste("<b> Moderation: ", "Dep = ", dep, "Pred = ", pred, "Mod = ", mod, "</b>"))
  moderation$mod %>% 
    knitr::kable(caption = "Moderation", digits = 3) %>%
    print()
  moderation$simpleSlope$plot %>%
    print()
}


Data_merged_wide_all %>%
  filter(!ID %in% c(19, 43)) %>%
  func_moderation(Data = ., dep = "OXT_Post_OGL", mod = "E", pred = "OXT_Pre_OGL")

Data_merged_wide_all %>%
  filter(!ID %in% c(19, 43)) %>%
  func_moderation(Data = ., dep = "OXT_Post_ECRAN", mod = "E", pred = "OXT_Pre_ECRAN")


cat("### ANCOVA - Extraversion")
df_ancova_e <-
  Data_merged_wide_all %>%
  select("ID", "OXT_Pre_OGL", "OXT_Post_OGL", "OXT_Pre_ECRAN", "OXT_Post_ECRAN", "E") %>%
  tidyr::drop_na() %>%
  gather("OXT_Pre_OGL", "OXT_Post_OGL", "OXT_Pre_ECRAN", "OXT_Post_ECRAN", key = "Cond", value = "value") %>%
  mutate(PrePost = case_when(stringr::str_detect(.$"Cond", "Pre") ~ "Pre",
                             stringr::str_detect(.$"Cond", "Post") ~ "Post",
                             TRUE ~ NA_character_),
         OglEcran = case_when(stringr::str_detect(.$"Cond", "OGL") ~ "OGL",
                              stringr::str_detect(.$"Cond", "ECRAN") ~ "ECRAN",
                              TRUE ~ NA_character_)) %>%
  mutate(PrePost = as.factor(PrePost),
         OglEcran = as.factor(OglEcran)) %>%
  select(-"Cond") %>%
  spread("PrePost", "value")


jmv::ancova(
    formula = Post ~ Pre + OglEcran + E,
    data = df_ancova_e,
    homo = TRUE,
    ss = "3",
    postHoc = ~ OglEcran,
    postHocCorr = list("tukey"),
    effectSize = list("eta", "partEta")
  )

4.9 Correlations between Diff_OXT_OGL with other variables

4.9.0.1 Correlations with Diff_OXT_OGL

4.9.0.2 Correlations with Diff_Vas_Stres_OGL

4.9.0.3 Correlations with Diff_Vas_Bine_OGL

4.9.0.4 Correlations with Diff_Vas_Bine_ECRAN

Call: lm(formula = Vas_Stres_Post_OGL ~ Vas_Stres_Pre_OGL + StaiTbrut, data = Data_merged_wide_all)

Residuals: Min 1Q Median 3Q Max -18.513 -4.540 1.046 3.503 20.137

Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) -9.31395 5.38906 -1.728 0.0905 .
Vas_Stres_Pre_OGL 0.73616 0.05491 13.406 <0.0000000000000002 ** StaiTbrut 0.26002 0.12212 2.129 0.0385
— Signif. codes: 0 ‘’ 0.001 ‘’ 0.01 ‘’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 8.039 on 47 degrees of freedom Multiple R-squared: 0.8065, Adjusted R-squared: 0.7983 F-statistic: 97.97 on 2 and 47 DF, p-value: < 0.00000000000000022

Call: lm(formula = Vas_Stres_Post_ECRAN ~ Vas_Stres_Pre_ECRAN + StaiTbrut, data = Data_merged_wide_all)

Residuals: Min 1Q Median 3Q Max -23.0762 -4.4267 -0.5844 4.6774 19.2660

Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 7.34215 6.03290 1.217 0.230
Vas_Stres_Pre_ECRAN 0.83186 0.05658 14.702 <0.0000000000000002 *** StaiTbrut -0.13710 0.14472 -0.947 0.348
— Signif. codes: 0 ‘’ 0.001 ‘’ 0.01 ‘’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 8.858 on 46 degrees of freedom (1 observation deleted due to missingness) Multiple R-squared: 0.8373, Adjusted R-squared: 0.8302 F-statistic: 118.4 on 2 and 46 DF, p-value: < 0.00000000000000022

Call: lm(formula = Vas_Bine_Post_OGL ~ Vas_Bine_Pre_OGL + ScorBDI, data = Data_merged_wide_all)

Residuals: Min 1Q Median 3Q Max -31.928 -7.000 0.981 6.480 31.480

Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 15.69505 6.62844 2.368 0.0221 *
Vas_Bine_Pre_OGL 0.89920 0.08809 10.208 0.000000000000164 ** ScorBDI -0.62074 0.26139 -2.375 0.0217
— Signif. codes: 0 ‘’ 0.001 ‘’ 0.01 ‘’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 11.54 on 47 degrees of freedom Multiple R-squared: 0.7015, Adjusted R-squared: 0.6888 F-statistic: 55.24 on 2 and 47 DF, p-value: 0.0000000000004571

Call: lm(formula = Vas_Bine_Post_ECRAN ~ Vas_Bine_Pre_ECRAN + ScorBDI, data = Data_merged_wide_all)

Residuals: Min 1Q Median 3Q Max -21.9414 -4.4338 -0.7211 5.6113 23.7907

Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 10.67270 5.16231 2.067 0.0443 *
Vas_Bine_Pre_ECRAN 0.90116 0.06273 14.366 <0.0000000000000002 *** ScorBDI -0.10869 0.20274 -0.536 0.5945
— Signif. codes: 0 ‘’ 0.001 ‘’ 0.01 ‘’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 8.741 on 46 degrees of freedom (1 observation deleted due to missingness) Multiple R-squared: 0.8259, Adjusted R-squared: 0.8183 F-statistic: 109.1 on 2 and 46 DF, p-value: < 0.00000000000000022

4.10 Correlations between Diff_OXT_OGL with other variables - by Gender

4.10.1 Females

4.10.1.1 Correlations with Diff_OXT_OGL

4.10.1.2 Correlations with Diff_Vas_Stres_OGL

4.10.1.3 Correlations with Diff_Vas_Bine_OGL

4.10.1.4 Correlations with Diff_Vas_Bine_ECRAN

4.10.2 Males

4.10.2.1 Correlations with Diff_OXT_OGL

4.10.2.2 Correlations with Diff_Vas_Stres_OGL

4.10.2.3 Correlations with Diff_Vas_Bine_OGL

4.10.2.4 Correlations with Diff_Vas_Bine_ECRAN

5 within-participant mediation

Pearson's product-moment correlation

data: df_cordif_fem\(Diff_OXT_OGL and df_cordif_fem\)Diff_Vas_Stres_OGL t = 0.21086, df = 22, p-value = 0.8349 alternative hypothesis: true correlation is not equal to 0 95 percent confidence interval: -0.3651008 0.4403297 sample estimates: cor 0.04491029

Call: lm(formula = Diff_OXT_OGL ~ Diff_Vas_Stres_OGL, data = df_cordif_fem)

Residuals: Min 1Q Median 3Q Max -0.62386 -0.15832 -0.07481 0.09697 1.18405

Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.176485 0.089349 1.975 0.0609 . Diff_Vas_Stres_OGL 0.001570 0.007445 0.211 0.8349
— Signif. codes: 0 ‘’ 0.001 ‘’ 0.01 ‘’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.3689 on 22 degrees of freedom (3 observations deleted due to missingness) Multiple R-squared: 0.002017, Adjusted R-squared: -0.04335 F-statistic: 0.04446 on 1 and 22 DF, p-value: 0.8349

6 Test of mediation (within-participant mediation)

Variables:

Paths:

==== ============== ===== ====================== Path Point estimate SE APA
==== ============== ===== ====================== a -0.166 0.074 t(23) = 2.26, p = .034 b 3.656 6.764 t(21) = 0.54, p = .595 c 6.185 2.137 t(26) = 2.89, p = .008 c’ 7.067 2.444 t(21) = 2.89, p = .009 ==== ============== ===== ======================

Indirect effect index:

Fitted models:

7 Test of mediation (within-participant mediation)

Variables:

Paths:

==== ============== ===== ====================== Path Point estimate SE APA
==== ============== ===== ====================== a -0.058 0.062 t(23) = 0.93, p = .360 b 4.307 5.702 t(21) = 0.76, p = .458 c 4.923 1.988 t(25) = 2.48, p = .020 c’ 3.417 1.731 t(21) = 1.97, p = .062 ==== ============== ===== ======================

Indirect effect index:

Fitted models:

8 Session Info

R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 8.1 x64 (build 9600)

Matrix products: default

locale:
[1] LC_COLLATE=Romanian_Romania.1250  LC_CTYPE=Romanian_Romania.1250    LC_MONETARY=Romanian_Romania.1250 LC_NUMERIC=C                     
[5] LC_TIME=Romanian_Romania.1250    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] JSmediation_0.1.0  GGally_1.4.0       rio_0.5.16         plyr_1.8.4         summarytools_0.8.8 DT_0.5             ggpubr_0.2        
 [8] magrittr_1.5       broom_0.5.2        papaja_0.1.0.9842  psych_1.8.12       forcats_0.4.0      stringr_1.4.0      dplyr_0.8.3       
[15] purrr_0.3.2        readr_1.3.1        tidyr_1.0.0        tibble_2.1.3       ggplot2_3.2.1      tidyverse_1.2.1    pacman_0.5.1      

loaded via a namespace (and not attached):
 [1] TH.data_1.0-9      jmvcore_1.0.8      colorspace_1.4-1   ggsignif_0.4.0     rjson_0.2.20       pryr_0.1.4         ellipsis_0.3.0    
 [8] estimability_1.3   base64enc_0.1-3    rstudioapi_0.8     mvtnorm_1.0-11     lubridate_1.7.4    xml2_1.2.0         codetools_0.2-16  
[15] splines_3.6.1      mnormt_1.5-5       knitr_1.25         zeallot_0.1.0      jsonlite_1.6       shiny_1.2.0        compiler_3.6.1    
[22] httr_1.4.0         emmeans_1.4.1      backports_1.1.4    assertthat_0.2.1   Matrix_1.2-17      lazyeval_0.2.2     cli_1.1.0         
[29] later_0.7.5        prettyunits_1.0.2  htmltools_0.3.6    tools_3.6.1        coda_0.19-2        gtable_0.3.0       glue_1.3.1        
[36] reshape2_1.4.3     Rcpp_1.0.2         carData_3.0-2      cellranger_1.1.0   vctrs_0.2.0        nlme_3.1-140       crosstalk_1.0.0   
[43] xfun_0.9           openxlsx_4.1.0     rvest_0.3.2        mime_0.7           lifecycle_0.1.0    MASS_7.3-51.4      zoo_1.8-4         
[50] scales_1.0.0       hms_0.5.1          promises_1.0.1     parallel_3.6.1     sandwich_2.5-0     RColorBrewer_1.1-2 yaml_2.2.0        
[57] curl_3.2           pander_0.6.3       reshape_0.8.8      stringi_1.4.3      highr_0.8          zip_1.0.0          rlang_0.4.0       
[64] pkgconfig_2.0.3    matrixStats_0.54.0 bitops_1.0-6       evaluate_0.14      lattice_0.20-38    rapportools_1.0    htmlwidgets_1.3   
[71] labeling_0.3       tidystats_0.3      tidyselect_0.2.5   R6_2.4.0           generics_0.0.2     multcomp_1.4-8     pillar_1.4.2      
[78] haven_2.1.1        foreign_0.8-71     withr_2.1.2        survival_2.44-1.1  abind_1.4-5        RCurl_1.95-4.11    modelr_0.1.5      
[85] crayon_1.3.4       car_3.0-2          rmarkdown_1.17     progress_1.2.0     grid_3.6.1         readxl_1.1.0       data.table_1.11.8 
[92] digest_0.6.21      xtable_1.8-4       httpuv_1.4.5       munsell_0.5.0      jmv_1.0.8         
 

A work by Claudiu Papasteri

 

LS0tDQp0aXRsZTogIjxicj4gTy40IEZyb250aWVycyBPWFQiIA0Kc3VidGl0bGU6ICJPWFQgYW5kIFBzaWNob2xvZ2ljYWwgdmFyaWFibGVzIC0gQnkgR2VuZGVyIg0KYXV0aG9yOiAiPGJyPiBDbGF1ZGl1IFBhcGFzdGVyaSINCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVtICVZJylgIg0Kb3V0cHV0OiANCiAgICBodG1sX25vdGVib29rOg0KICAgICAgICAgICMgc2VsZl9jb250YWluZWQ6IG5vDQogICAgICAgICAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICAgICAgICAgIHRvYzogdHJ1ZQ0KICAgICAgICAgICAgdG9jX2RlcHRoOiAyDQogICAgICAgICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICAgICAgICAgIHRoZW1lOiBzcGFjZWxhYg0KICAgICAgICAgICAgaGlnaGxpZ2h0OiB0YW5nbw0KICAgICAgICAgICAgZm9udC1mYW1pbHk6IEFyaWFsDQogICAgICAgICAgICBmaWdfd2lkdGg6IDEwDQogICAgICAgICAgICBmaWdfaGVpZ2h0OiA5DQogICAgICMgcGRmX2RvY3VtZW50OiANCiAgICAgICAgICAgICMgdG9jOiB0cnVlDQogICAgICAgICAgICAjIHRvY19kZXB0aDogMg0KICAgICAgICAgICAgIyBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICAgICAgICAgICMgZm9udHNpemU6IDExcHQNCiAgICAgICAgICAgICMgZ2VvbWV0cnk6IG1hcmdpbj0xaW4NCiAgICAgICAgICAgICMgZmlnX3dpZHRoOiA3DQogICAgICAgICAgICAjIGZpZ19oZWlnaHQ6IDYNCiAgICAgICAgICAgICMgZmlnX2NhcHRpb246IHRydWUNCiAgICAjIGdpdGh1Yl9kb2N1bWVudDogDQogICAgICAgICAgICAjIHRvYzogdHJ1ZQ0KICAgICAgICAgICAgIyB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgICMgaHRtbF9wcmV2aWV3OiBmYWxzZQ0KICAgICAgICAgICAgIyBmaWdfd2lkdGg6IDUNCiAgICAgICAgICAgICMgZmlnX2hlaWdodDogNQ0KICAgICAgICAgICAgIyBkZXY6IGpwZWcNCi0tLQ0KDQoNCjwhLS0gU2V0dXAgLS0+DQoNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGtpbnRyIG9wdGlvbnMNCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgY29tbWVudCA9ICIjIiwNCiAgY29sbGFwc2UgPSBUUlVFLA0KICBlcnJvciA9IEZBTFNFLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGlzIG5lZWRzIHRvIGJlIHN1cHJlc3NlZCB3aGVuIHJ1bmluZyB0ZXN0cyAgICAgICAgICAgICAgIA0KICBlY2hvID0gVFJVRSwgd2FybmluZyA9IFRSVUUsIG1lc3NhZ2UgPSBUUlVFLCBjYWNoZSA9IFRSVUUgICAgICAgIyBlY2hvID0gRmFsc2UgZm9yIGdpdGh1Yl9kb2N1bWVudCwgYnV0IHdpbGwgYmUgZm9sZGVkIGluIGh0bWxfbm90ZWJvb2sNCikNCg0KIyBrbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9IG5vcm1hbGl6ZVBhdGgoIkM6L1VzZXJzL01paGFpL0Rlc2t0b3AvUiBOb3RlYm9va3Mvbm90ZWJvb2tzL08uNC01MHN1YiBGcm9udGllcnMgT1hUIEdlbmRlciIpKQ0KDQojIEdlbmVyYWwgUiBvcHRpb25zIGFuZCBpbmZvDQpzZXQuc2VlZCgxMTEpICAgICAgICAgICAgICAgIyBpbiBjYXNlIHdlIHVzZSByYW5kb21pemVkIHByb2NlZHVyZXMgICAgICAgDQpvcHRpb25zKHNjaXBlbiA9IDk5OSkgICAgICAgIyBwb3NpdGl2ZSB2YWx1ZXMgYmlhcyB0b3dhcmRzIGZpeGVkIGFuZCBuZWdhdGl2ZSB0b3dhcmRzIHNjaWVudGlmaWMgbm90YXRpb24NCg0KIyBMb2FkIHBhY2thZ2VzDQppZiAoIXJlcXVpcmUoInBhY21hbiIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKQ0KcGFja2FnZXMgPC0gYygNCiAgInRpZHl2ZXJzZSIsICAgICAgIyBiZXN0IHRoaW5nIHRoYXQgaGFwcGVuZCB0byBtZQ0KICAicHN5Y2giLCAgICAgICAgICAjIGdlbmVyYWwgcHVycG9zZSB0b29sYm94IGZvciBwZXJzb25hbGl0eSwgcHN5Y2hvbWV0cmljIHRoZW9yeSBhbmQgZXhwZXJpbWVudGFsIHBzeWNob2xvZ3kNCiAgInBhcGFqYSIsICAgICAgICAgIyBmb3IgQVBBIHN0eWxlDQogICJicm9vbSIsICAgICAgICAgICMgZm9yIHRpZHkgbW9kZWxsaW5nDQogICJnZ3Bsb3QyIiwgICAgICAgICMgYmVzdCBwbG90cw0KICAiZ2dwdWJyIiwgICAgICAgICAjIGdncGxvdDIgdG8gcHVibGljYXRpb24gcXVhbGl0eQ0KICAiRFQiLCAgICAgICAgICAgICAjIG5pY2Ugc2VhcmNoYWJsZSBhbmQgZG93bmxvYWRhYmxlIHRhYmxlcw0KICAic3VtbWFyeXRvb2xzIiwNCiAgInBseXIiLCANCiAgInJpbyIsDQogICJHR2FsbHkiDQogICMgLCAuLi4NCikNCmlmICghcmVxdWlyZSgicGFjbWFuIikpIGluc3RhbGwucGFja2FnZXMoInBhY21hbiIpDQpwYWNtYW46OnBfbG9hZChjaGFyID0gcGFja2FnZXMpDQoNCiMgVGhlbWVzIGZvciBnZ3Bsb3QyIHBsb3RpbmcgKGhlcmUgdXNlZCBBUEEgc3R5bGUpDQp0aGVtZV9zZXQodGhlbWVfYXBhKCkpDQpgYGANCg0KDQoNCjwhLS0gUmVwb3J0IC0tPg0KDQoNCiMgUmVhZCBhbmQgTWVyZ2UNCg0KDQpgYGB7ciByZWFkLCByZXN1bHRzPSdhc2lzJywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiMgUmVhZCANCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCndkIDwtICJDOi9Vc2Vycy9NaWhhaS9EZXNrdG9wL08uNCBwcmVhbGFiaWwgcHQgRnJvbnRpZXJzL08uNCBEYXRlIFBzaWhvJk9YVCINCnNldHdkKHdkKQ0KDQpEYXRhX09YVCA8LSByaW86OmltcG9ydChmaWxlLnBhdGgod2QsICJcXE9YVCIsICJPLjQgT1hUIERhdGEueGxzeCIpKQ0KDQpEYXRhX3BzaWggPC0gcmlvOjppbXBvcnQoZmlsZS5wYXRoKHdkLCAiXFxQc2lobyIsICJEQVRFIE80Q2wgMTYuMTEuMjAxOSBwcm9jZXNhdC54bHN4IiksIHdoaWNoID0gIjI2bWFydGllMjAxOSIpDQpEYXRhX3BzaWggPC0gRGF0YV9wc2loWywgYygxOjYsIDg6MTMpXQ0KDQpEYXRhX05lbyA8LSByaW86OmltcG9ydChmaWxlLnBhdGgod2QsICJcXFBzaWhvIiwgIkRBVEUgTzRDbCAxNi4xMS4yMDE5IHByb2Nlc2F0Lnhsc3giKSwgd2hpY2ggPSAiTmVvIHNjb3JlZCIpDQpEYXRhX0JESSA8LSByaW86OmltcG9ydChmaWxlLnBhdGgod2QsICJcXFBzaWhvIiwgIkRBVEUgTzRDbCAxNi4xMS4yMDE5IHByb2Nlc2F0Lnhsc3giKSwgd2hpY2ggPSAiQkRJIHNjb3JlZCIpDQpEYXRhX1NUQUkgPC0gcmlvOjppbXBvcnQoZmlsZS5wYXRoKHdkLCAiXFxQc2lobyIsICJEQVRFIE80Q2wgMTYuMTEuMjAxOSBwcm9jZXNhdC54bHN4IiksIHdoaWNoID0gIlNUQUkgc2NvcmVkIikNCg0KYGBgDQoNCg0KDQpgYGB7ciBjbGVhbiwgcmVzdWx0cz0nYXNpcyd9DQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQojIENsZWFuICYgTWVyZ2UNCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCkRhdGFfU1RBSSA8LSANCiAgRGF0YV9TVEFJICU+JSANCiAgZHBseXI6OmZpbHRlcighaXMubmEoSUQpKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBubyBJRCwgbm8gZGF0YQ0KICBkcGx5cjo6ZmlsdGVyKHJvd1N1bXMoaXMubmEoLikpIDwgMikgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGZpbHRlciBvdXQgcm93cyAobm8gbW9yZSB0aGFuIDEgTkEgb24gcm93KQ0KICBtdXRhdGUoSUQgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZShJRCwgIlxccyIsICJ8IikpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJlcGxhY2UgZmlyc3Qgd2hpdGVzcGFjZSB3aXRoIHwgYW5kIHVzZSBpdCB0byBzZXBhcmF0ZQ0KICB0aWR5cjo6c2VwYXJhdGUoSUQsIGludG8gPSBjKCJJRCIsICJFeHBlcmltIiksIHNlcCA9ICJcXHwiKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHNlcGFyYXRlIG9uIG9ubHkgZmlyc3Qgd2hpdGVzcGFjZSB0aGF0IHdhcyByZXBsYWNlZA0KICBkcGx5cjo6c2VsZWN0KC1FeHBlcmltKQ0KDQpEYXRhX0JESSA8LSANCiAgRGF0YV9CREkgJT4lIA0KICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShJRCkpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG5vIElELCBubyBkYXRhDQogIGRwbHlyOjpmaWx0ZXIocm93U3Vtcyhpcy5uYSguKSkgPCAxKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgZmlsdGVyIG91dCByb3dzIChub3QgMSBOQSkNCiAgbXV0YXRlKElEID0gc3RyaW5ncjo6c3RyX3JlcGxhY2UoSUQsICJcXHMiLCAifCIpKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyByZXBsYWNlIGZpcnN0IHdoaXRlc3BhY2Ugd2l0aCB8IGFuZCB1c2UgaXQgdG8gc2VwYXJhdGUNCiAgdGlkeXI6OnNlcGFyYXRlKElELCBpbnRvID0gYygiSUQiLCAiRXhwZXJpbSIpLCBzZXAgPSAiXFx8IikgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzZXBhcmF0ZSBvbiBvbmx5IGZpcnN0IHdoaXRlc3BhY2UgdGhhdCB3YXMgcmVwbGFjZWQNCiAgZHBseXI6OnNlbGVjdCgtRXhwZXJpbSkNCg0KRGF0YV9OZW8gPC0gDQogIERhdGFfTmVvICU+JSANCiAgZHBseXI6OmZpbHRlcighaXMubmEoSUQpKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBubyBJRCwgbm8gZGF0YQ0KICBkcGx5cjo6ZmlsdGVyKHJvd1N1bXMoaXMubmEoLikpIDwgNikgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGZpbHRlciBvdXQgcm93cyAobm8gbW9yZSB0aGFuIDUgTkEgb24gcm93KQ0KICBtdXRhdGUoSUQgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZShJRCwgIlxccyIsICJ8IikpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJlcGxhY2UgZmlyc3Qgd2hpdGVzcGFjZSB3aXRoIHwgYW5kIHVzZSBpdCB0byBzZXBhcmF0ZQ0KICB0aWR5cjo6c2VwYXJhdGUoSUQsIGludG8gPSBjKCJJRCIsICJFeHBlcmltIiksIHNlcCA9ICJcXHwiKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHNlcGFyYXRlIG9uIG9ubHkgZmlyc3Qgd2hpdGVzcGFjZSB0aGF0IHdhcyByZXBsYWNlZA0KICBkcGx5cjo6c2VsZWN0KC1FeHBlcmltKQ0KDQpEYXRhX3BzaWggPC0gDQogIERhdGFfcHNpaCAlPiUgDQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKElEKSkgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbm8gSUQsIG5vIGRhdGENCiAgZHBseXI6OmZpbHRlcihyb3dTdW1zKGlzLm5hKC4pKSA8IDgpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBmaWx0ZXIgb3V0IHJvd3MgKG5vIG1vcmUgdGhhbiA3IE5BIG9uIHJvdykNCiAgdGlkeXI6OnNlcGFyYXRlKENvbmRpdGlhLCAgYygiTnJfemkiLCAiQ29uZGl0aWEiKSwgIlxccysiKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzcGxpdCBvbiB3aGl0ZSBzcGFjZQ0KICBtdXRhdGUoSUQgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZShJRCwgIlxccyIsICJ8IikpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJlcGxhY2UgZmlyc3Qgd2hpdGVzcGFjZSB3aXRoIHwgYW5kIHVzZSBpdCB0byBzZXBhcmF0ZQ0KICB0aWR5cjo6c2VwYXJhdGUoSUQsIGludG8gPSBjKCJJRCIsICJFeHBlcmltIiksIHNlcCA9ICJcXHwiKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHNlcGFyYXRlIG9uIG9ubHkgZmlyc3Qgd2hpdGVzcGFjZSB0aGF0IHdhcyByZXBsYWNlZA0KICBkcGx5cjo6cmVuYW1lKCJOdW1lIiA9IE51bWVfUHJlbnVtZSkgJT4lIA0KICBkcGx5cjo6c2VsZWN0KC1FeHBlcmltKQ0KDQpEYXRhX09YVCA8LSAgIA0KICBEYXRhX09YVCAlPiUgDQogIHRpZHlyOjpzZXBhcmF0ZShJRCwgIGMoIklEIiwgIlppdWEiLCAiTnJfemkiLCAiUHJvYmEiKSwgIlxccysiKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICMgc3BsaXQgb24gd2hpdGUgc3BhY2UNCiAgc2VsZWN0KElELCBOcl96aSwgUHJvYmEsIE9YVCkgJT4lDQogIHRpZHlyOjpzZXBhcmF0ZShJRCwgaW50byA9IGMoIklEIiwgIkV4cGVyaW0iKSwgc2VwID0gIlxcLyIpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgc2VwYXJhdGUgb24gLw0KICBkcGx5cjo6c2VsZWN0KC1FeHBlcmltKSAlPiUgDQogIGRwbHlyOjpyZW5hbWUoIlByZVBvc3QiID0gUHJvYmEpICU+JSANCiAgbXV0YXRlKFByZVBvc3QgPSBmb3JjYXRzOjpmY3RfcmVjb2RlKFByZVBvc3QsICJQcmUiID0gIkEiLCAiUG9zdCIgPSAiQiIpKSAlPiUgICAgICAgICAgICAgICAgIyBQcm9iYSBBID0gUHJlLCBCID0gUG9zdCBvbiBzYW1lIGRheQ0KICBzcHJlYWQoa2V5ID0gUHJlUG9zdCwgdmFsdWUgPSBPWFQpICU+JQ0KICBkcGx5cjo6cmVuYW1lX2F0KHZhcnMoUHJlLCBQb3N0KSwgfiBjKCJPWFRfUHJlIiwgIk9YVF9Qb3N0IikpDQoNCg0KRGF0YV9tZXJnZWQgPC0gZHBseXI6OmxlZnRfam9pbihEYXRhX3BzaWgsIERhdGFfT1hULCBieSA9IGMoIklEIiwgIk5yX3ppIikpICAgICAgICAgICAgICAgICAjIElEIDQwLCA1OSBhcmUgaW5jb21wbGV0ZSBpbiBPWFQgLS0gZHBseXI6OmZ1bGxfam9pbg0KDQoNCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiMgTWFrZSBXaWRlIERhdGFmcmFtZSBvZiBtZXJnZWQNCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiMgQ2hlY2sgaWYgaWRzIGhhdmUgPiAxIHJvdyBvZiBkYXRhIChlbXB0eSBJRCBoYXZlIG9ubHkgMSByb3c7IHRoZWkgaGF2ZSBvbmx5IDEgQ29uZGl0aW9uKSANCiMgQ2FyZWZ1bCEgVGhpcyBmdW5jdGlvbiBtb2RmaWVzIHRoZSBkYXRhc2V0cyBpbiB0aGUgZ2xvYmFsIGVudmlucm9ubWVudA0KZGVsZXRlX2VtcHR5X2lkIDwtIGZ1bmN0aW9uKGRmKXsNCiAgbGlzdF9lbXB0eV9pZCA8LSANCiAgICBkZiAlPiUNCiAgICBkcGx5cjo6Z3JvdXBfYnkoSUQpICU+JQ0KICAgIGRwbHlyOjpzdW1tYXJpc2Uocm93X2NvdW50ID0gbigpKSAlPiUNCiAgICBkcGx5cjo6cmVuYW1lKCJlbXB0eV9pZCIgPSBJRCkgJT4lDQogICAgbXV0YXRlKGRlbGV0ZV9pZCA9IGlmX2Vsc2Uocm93X2NvdW50IDwgMiwgVFJVRSwgRkFMU0UpKSAlPiUNCiAgICBmaWx0ZXIoZGVsZXRlX2lkID09IFRSVUUpDQogIA0KICBkZl9tb2RpZiA8LSANCiAgICBkZiAlPiUNCiAgICBmaWx0ZXIoIUlEICVpbiUgbGlzdF9lbXB0eV9pZCRlbXB0eV9pZCkNCiAgDQogIGlmKCFpZGVudGljYWwoZGYsIGRmX21vZGlmKSl7DQogICAgZGYgPC0gZGVwYXJzZShzdWJzdGl0dXRlKGRmKSkNCiAgICBjYXQoIkRlbGV0aW5nIGZyb20gIiwgcHJpbnQoYXMubmFtZShkZikpKTsgcHJpbnQobGlzdF9lbXB0eV9pZCkgICAgICAgICAgICAgICAgICAgICMgcHJpbnQgb3V0IHdoaWNoIGlkcyBhcmUgZGVsZXRlZCBmcm9tIHdoaWNoIGRhdGFzZXQNCiAgICBhc3NpZ24oZGYsIGRmX21vZGlmLCBlbnZpciA9IGdsb2JhbGVudigpKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgYXNzaWduIG1vZGlmaWVkIGRmIHRvIG9yaWdpbmFsIGRhdGFzZXQgZnJvbSBHbG9iYWwNCiAgfWVsc2UgY2F0KCJObyBlbXB0eSBkYXRhc2V0cy4gTm90aGluZyB0byBkZWxldGUiKQ0KfQ0KZGVsZXRlX2VtcHR5X2lkKERhdGFfbWVyZ2VkKSANCg0KIyBEYXRhZnJhbWUgZm9yIHJlZ3VsYXIgYW5hbHlzZXMNCkRhdGFfbWVyZ2VkX3dpZGUgPC0NCiAgRGF0YV9tZXJnZWQgJT4lDQogIHNlbGVjdCgtYyhWYXJzdGEsIEdlbikpICU+JSAgICAgICAgICAgICMgZXhjbHVkZSBHZW4sIFZhcnN0YTogbWVyZ2UgYWZ0ZXIgYmVjYXVzZSBpdCBpbnRlcmZlcmVzIHdpdGggc3ByZWFkKCkNCiAgZ2F0aGVyKCJ2YXJpYWJsZSIsICJ2YWx1ZSIsIGMoRGF0YSwgTnJfemksIFZhc19TdHJlc19QcmU6T1hUX1Bvc3QpLCAtYygxOjIpKSAlPiUgICAgICAgIyBDb25kaXRpYSBuZWVkcyB0byBiZSBvdXRzaWRlDQogIHVuaXRlKCJ1bml0ZWRfdmFyIiwgYyh2YXJpYWJsZSwgQ29uZGl0aWEpLCBzZXAgPSAiXyIpICU+JQ0KICBzcHJlYWQodW5pdGVkX3ZhciwgdmFsdWUpICU+JQ0KICBtdXRhdGVfYXQodmFycyg1OjIyKSwgbGlzdCh+YXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoLikpKSkNCg0KIyBzdW0oaXMubmEoRGF0YV9tZXJnZWRbLCA2OjE1XSkpID09IHN1bShpcy5uYShEYXRhX21lcmdlZF93aWRlWywgNToyMl0pKSAgICAjIGNoZWNrIGlmIG5yIG9mIE5BIGlzIHRoZSBzYW1lIGFmdGVyIG1lbHQNCg0KDQojIEZ1bGwgV2lkZSBEYXRhZnJhbWUgIChIRVJFIFdlIEFQUExZIEVYQ0xVU0lPTiBDUklURVJJQSkgDQpEYXRhX21lcmdlZF93aWRlX2FsbCA8LSANCiAgRGF0YV9tZXJnZWRbLCBjKCJJRCIsICJOdW1lIiwgIlZhcnN0YSIsICJHZW4iKV0gJT4lICAgICAgICAgICAgICAgICAgICAgICAgIyBuZWVkIHRvIGFkZCB0aGVzZSBiYWNrLCBidXQganVzdCB0aGUgbWFpbiB1bmR1cGxpY2F0ZWQgcm93DQogIGRwbHlyOjpkaXN0aW5jdChJRCwgLmtlZXBfYWxsID0gVFJVRSkgJT4lDQogICAgZHBseXI6OmxlZnRfam9pbiguLCBEYXRhX21lcmdlZF93aWRlLCBieSA9ICJJRCIpICU+JQ0KICAgIGRwbHlyOjpyZW5hbWUoIk51bWUiID0gTnVtZS54KSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KC1OdW1lLnkpICU+JSANCiAgICBkcGx5cjo6bGVmdF9qb2luKC4sIERhdGFfQkRJLCBieSA9ICJJRCIpICU+JQ0KICAgIGRwbHlyOjpsZWZ0X2pvaW4oLiwgRGF0YV9TVEFJLCBieSA9ICJJRCIpICU+JQ0KICAgIGRwbHlyOjpsZWZ0X2pvaW4oLiwgRGF0YV9OZW8sIGJ5ID0gIklEIikgJT4lDQogICAgbXV0YXRlX2F0KHZhcnMoMjM6NjApLCBsaXN0KH5hcy5udW1lcmljKGFzLmNoYXJhY3RlciguKSkpKSAlPiUNCiAgICBtdXRhdGUoVmFyc3RhID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoVmFyc3RhKSkpICU+JSANCiAgICBmaWx0ZXIoIUlEICVpbiUgYygxOSwgNDMpKSAlPiUgICAgICAgICAgICMgNTUgc3VicyByZW1haW4gYWZ0ZXIgdGhpcw0KICAgIGZpbHRlcihWYXJzdGEgPCA0MCkgJT4lICAgICAgICAgICAgICAgICAgIyA1MyBzdWJzIHJlbWFpbiBhZnRlciB0aGlzDQogICAgZmlsdGVyKFNjb3JCREkgPCAzMCkgJT4lICAgICAgICAgICAgICAgICAjIDUwIHN1YnMgcmVtYWluIGFmdGVyIHRoaXMNCiAgICBkcGx5cjo6YXJyYW5nZShJRCkNCg0KDQojIEZ1bGwgTG9uZyBEYXRhZnJhbWUNCnZhcnNfT2dsRWNyYW4gPC0gZ3JlcCgiT0dMfEVDUkFOIiwgY29sbmFtZXMoRGF0YV9tZXJnZWRfd2lkZV9hbGwpKQ0KDQpEYXRhX21lcmdlZF9sb25nX2FsbCA8LQ0KICBEYXRhX21lcmdlZF93aWRlX2FsbCAlPiUNCiAgZ2F0aGVyKHZhcmlhYmxlLCB2YWx1ZSwgdmFyc19PZ2xFY3JhbiwgLWMoSUQpKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgZ2F0aGVyIERhdGEgYW5kIE5yX3ppIGFzIHRoZXNlIGFyZSBPZ2xFY3JhbiBsZXZlbA0KICB0aWR5cjo6c2VwYXJhdGUodmFyaWFibGUsICBjKCJ2YXJpYWJsZSIsICJPZ2xFY3JhbiIpLCAiXyg/PVteX10rJCkiKSAlPiUgICAgICAgICAgICAgICAgIyBzcGxpdCBvbmx5IG9uIGxhc3QgIl8iDQogIHNwcmVhZCh2YXJpYWJsZSwgdmFsdWUpICU+JSANCiAgcmVuYW1lX2F0KHZhcnModmFyc19PZ2xFY3JhbiksIGxpc3QofnN0cmluZ3I6OnN0cl9yZW1vdmVfYWxsKC4sIGMoIl9PR0x8X0VDUkFOIikpKSkgJT4lICAgICAgICAgIA0KICBhcnJhbmdlKElEKQ0KDQp2YXJzX1ByZVBvc3QgPC0gZ3JlcCgiUHJlfFBvc3QiLCBjb2xuYW1lcyhEYXRhX21lcmdlZF9sb25nX2FsbCkpDQoNCkRhdGFfbWVyZ2VkX2xvbmdfYWxsIDwtDQogIERhdGFfbWVyZ2VkX2xvbmdfYWxsICU+JQ0KICBwaXZvdF9sb25nZXIodmFyc19QcmVQb3N0LCBuYW1lc190byA9IGMoIi52YWx1ZSIsIlByZVBvc3QiKSwgbmFtZXNfcGF0dGVybiA9ICIoLiopXyguKikiKSAlPiUgICAgICMgbWFnaWMgICAgIA0KICBtdXRhdGVfYXQodmFycyg0ODo1MCksIGxpc3QofmFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKC4pKSkpICU+JQ0KICBhcnJhbmdlKElEKQ0KDQoNCiMgRmVtYWxlcyBhbmQgTWFsZXMgRGF0YWZyYW1lcw0KRGF0YV9mZW0gPC0gDQogIERhdGFfbWVyZ2VkX3dpZGVfYWxsICU+JQ0KICBmaWx0ZXIoR2VuID09ICJmIikNCkRhdGFfbWFzYyA8LSANCiAgRGF0YV9tZXJnZWRfd2lkZV9hbGwgJT4lDQogIGZpbHRlcihHZW4gPT0gIm0iKQ0KDQojIERpZmZlcmVuY2UgU2NvcmVzIERhdGFmcmFtZQ0KRGF0YV9kaWZzY29yZXMgPC0NCiAgRGF0YV9tZXJnZWRfd2lkZV9hbGwgJT4lDQogIG11dGF0ZShEaWZmX09YVF9PR0wgPSBPWFRfUG9zdF9PR0wgLSBPWFRfUHJlX09HTCwNCiAgICAgICAgIERpZmZfT1hUX0VDUkFOID0gT1hUX1Bvc3RfRUNSQU4gLSBPWFRfUHJlX0VDUkFOLA0KICAgICAgICAgRGlmZl9WYXNfU3RyZXNfT0dMID0gVmFzX1N0cmVzX1Bvc3RfT0dMIC0gVmFzX1N0cmVzX1ByZV9PR0wsDQogICAgICAgICBEaWZmX1Zhc19TdHJlc19FQ1JBTiA9IFZhc19TdHJlc19Qb3N0X0VDUkFOIC0gVmFzX1N0cmVzX1ByZV9FQ1JBTiwgDQogICAgICAgICBEaWZmX1Zhc19CaW5lX09HTCA9IFZhc19CaW5lX1Bvc3RfT0dMIC0gVmFzX0JpbmVfUHJlX09HTCwNCiAgICAgICAgIERpZmZfVmFzX0JpbmVfRUNSQU4gPSBWYXNfQmluZV9Qb3N0X0VDUkFOIC0gVmFzX0JpbmVfUHJlX0VDUkFOLA0KICAgICAgICAgRGlmZl9JT1NfT0dMID0gSU9TX1Bvc3RfT0dMIC0gSU9TX1ByZV9PR0wsDQogICAgICAgICBEaWZmX0lPU19FQ1JBTiA9IElPU19Qb3N0X0VDUkFOIC0gSU9TX1ByZV9FQ1JBTg0KICApIA0KYGBgDQoNCg0KIyMgRGF0YXNldCAtIExvbmcgRm9ybWF0DQoNCmBgYHtyIGRmX2V4Y2VsX2xvbmd9DQpEYXRhX21lcmdlZF9sb25nX2FsbCAlPiUNCiAgZHBseXI6OnNlbGVjdCgtTnVtZSkgJT4lDQogICAgRFQ6OmRhdGF0YWJsZSgNCiAgICAgIGV4dGVuc2lvbnMgPSAnQnV0dG9ucycsDQogICAgICBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTAsDQogICAgICAgICAgICAgICAgICAgICBzY3JvbGxYPSc1MDBweCcsDQogICAgICAgICAgICAgICAgICAgICBkb20gPSAnQmZydGlwJywNCiAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBjKCdleGNlbCcsICJjc3YiKSkpDQpgYGANCg0KDQojIyBEYXRhc2V0IC0gV2lkZSBGb3JtYXQNCg0KYGBge3IgZGZfZXhjZWxfd2lkZX0NCkRhdGFfbWVyZ2VkX3dpZGVfYWxsICU+JQ0KICBkcGx5cjo6c2VsZWN0KC1OdW1lKSAlPiUNCiAgICBEVDo6ZGF0YXRhYmxlKA0KICAgICAgZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywNCiAgICAgIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSAxMCwNCiAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFg9JzUwMHB4JywNCiAgICAgICAgICAgICAgICAgICAgIGRvbSA9ICdCZnJ0aXAnLA0KICAgICAgICAgICAgICAgICAgICAgYnV0dG9ucyA9IGMoJ2V4Y2VsJywgImNzdiIpKSkNCmBgYA0KDQoNCiMgRGVzY3JpcHRpdmVzDQoNCiMjIERlc2NyaXB0aXZlcyAtIEdlbiBWYXJzdGENCg0KYGBge3IgZGVzY19nZW5fdmFyc3RhfQ0KZGVzY3JpYmUoRGF0YV9tZXJnZWRfd2lkZV9hbGwkVmFyc3RhKQ0KcHJvcC50YWJsZSh0YWJsZShEYXRhX21lcmdlZF93aWRlX2FsbCRHZW4pKQ0KDQp0LnRlc3QoRGF0YV9tZXJnZWRfd2lkZV9hbGwkVmFyc3RhIH4gRGF0YV9tZXJnZWRfd2lkZV9hbGwkR2VuKSAlPiUNCiAgdGlkeSgpDQoNCndpbGNveC50ZXN0KERhdGFfbWVyZ2VkX3dpZGVfYWxsJFZhcnN0YSB+IERhdGFfbWVyZ2VkX3dpZGVfYWxsJEdlbikgJT4lDQogIHRpZHkoKQ0KDQpwc3ljaDo6ZGVzY3JpYmVCeShEYXRhX21lcmdlZF93aWRlX2FsbCRWYXJzdGEsIGdyb3VwID0gRGF0YV9tZXJnZWRfd2lkZV9hbGwkR2VuKQ0KYGBgDQoNCg0KIyMgUGxvdHMNCg0KYGBge3IgcGxvdF9nZW4sIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTYsIHJlc3VsdHM9J2FzaXMnfQ0KIyMgUGllIGNoYXJ0DQpEYXRhX21lcmdlZF93aWRlX2FsbCAgJT4lDQogIG11dGF0ZShHZW4gPSBhcy5mYWN0b3IoYXMuY2hhcmFjdGVyKEdlbikpKSAlPiUNCiAgbXV0YXRlKEdlbiA9IGZvcmNhdHM6OmZjdF9yZWNvZGUoR2VuLCAiZmVtaW4iID0gImYiLCAibWFzY3VsaW4iID0gIm0iKSkgJT4lDQogIGdyb3VwX2J5KEdlbikgJT4lDQogIGRwbHlyOjpzdW1tYXJpc2UoY291bnRzID0gbigpKSAlPiUNCiAgbXV0YXRlKHByb3AgPSByb3VuZChjb3VudHMqMTAwL3N1bShjb3VudHMpLCAxKSwNCiAgICAgICAgIGxhYi55cG9zID0gY3Vtc3VtKHByb3ApIC0gLjUqcHJvcCwNCiAgICAgICAgIFBlcmNlbnQgPSBwYXN0ZTAocHJvcCwgIiAlIikpICU+JSANCiAgZ2dwdWJyOjpnZ3BpZSh4ID0gInByb3AiLCBsYWJlbCA9ICJQZXJjZW50IiwNCiAgICAgICAgICAgICAgICBmaWxsID0gIkdlbiIsIGNvbG9yID0gIndoaXRlIiwgDQogICAgICAgICAgICAgICAgbGFiLnBvcyA9ICJpbiIsIGxhYi5mb250ID0gbGlzdChjb2xvciA9ICJ3aGl0ZSIpLA0KICAgICAgICAgICAgICAgIHBhbGV0dGUgPSAiZ3JleSIpDQpgYGANCg0KDQpgYGB7ciBwbG90X3ZhcnN0YV9nZW4sIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTYsIHJlc3VsdHM9J2FzaXMnLCB3YXJuaW5nPUZBTFNFfQ0KIyMgRG9kZ2VkIEJhciBwbG90IG9mIEFnZSBhbmQgR2VuZGVyDQpEYXRhX21lcmdlZF93aWRlX2FsbCAlPiUNCiAgbXV0YXRlKFZhcnN0YSA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKFZhcnN0YSkpKSAlPiUNCiAgbXV0YXRlKFZhcnRhX2NhdGVnID0gY3V0KFZhcnN0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3M9YygtSW5mLCAyNSwgMzAsIDM1LCA0MCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIjIwLTI0IiwiMjUtMjkiLCIzMC0zNCIsICIzNS0zOSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gRkFMU0UpKSAlPiUgIA0KICBtdXRhdGUoVmFyc3RhID0gYXMuZmFjdG9yKFZhcnN0YSksDQogICAgICAgICBHZW4gPSBhcy5mYWN0b3IoYXMuY2hhcmFjdGVyKEdlbikpKSAlPiUNCiAgbXV0YXRlKEdlbiA9IGZvcmNhdHM6OmZjdF9yZWNvZGUoR2VuLCAiZmVtaW4iID0gImYiLCAibWFzY3VsaW4iID0gIm0iKSkgJT4lDQogIGRwbHlyOjpjb3VudChWYXJ0YV9jYXRlZywgR2VuLCAuZHJvcCA9IEZBTFNFKSAlPiUgICAgICAgICAjIEdyb3VwIGJ5LCB0aGVuIGNvdW50IG51bWJlciBpbiBlYWNoIGdyb3VwIChkb250IGRyb3AgMCBjb3VudHMpDQogIG11dGF0ZShwY3QgPSBwcm9wLnRhYmxlKG4pKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAjIENhbGN1bGF0ZSBwZXJjZW50IHdpdGhpbiBlYWNoIHZhcg0KICAgIGdncGxvdChhZXMoeCA9IFZhcnRhX2NhdGVnLCB5ID0gcGN0LCBmaWxsID0gR2VuLCBsYWJlbCA9IHNjYWxlczo6cGVyY2VudChwY3QpKSkgKyANCiAgICAgIGdlb21fY29sKHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UocHJlc2VydmUgPSAic2luZ2xlIiksIHN0YXQgPSAiaWRlbnRpdHkiKSArICAgICMgRG9uJ3QgZHJvcCB6ZXJvIGNvdW50DQogICAgICBnZW9tX3RleHQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IC45KSwgICAgICAjIG1vdmUgdG8gY2VudGVyIG9mIGJhcnMNCiAgICAgICAgICAgICAgICB2anVzdCA9IC0wLjUsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbnVkZ2UgYWJvdmUgdG9wIG9mIGJhcg0KICAgICAgICAgICAgICAgIHNpemUgPSAzKSArIA0KICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKw0KICAgICAgZ2d0aXRsZSgiIikgKw0KICAgICAgeGxhYigiVmFyc3RhIikgKyB5bGFiKCJQZXJjZW50YWdlICUiKSArIA0KICAgICAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiR2VuIiwgbmNvbCA9IDEpKSArIA0KICAgICAgc2NhbGVfZmlsbF9ncmV5KHN0YXJ0ID0gMC44LCBlbmQgPSAwLjIsIG5hLnZhbHVlID0gInJlZCIsIGFlc3RoZXRpY3MgPSAiZmlsbCIpICsNCiAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIGxlZ2VuZC5kaXJlY3Rpb24gPSAidmVydGljYWwiLCANCiAgICAgICAgICAgIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAxKSwgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSwgY29sb3VyID0gImJsYWNrIikpDQpgYGANCg0KIyMgdCB0ZXN0IFZhcnN0YSBieSBHZW4NCg0KYGBge3IgdHRlc3RfdmFyc3RhX2dlbiwgd2FybmluZz1GQUxTRX0NCiMgR2VuDQpEYXRhX21lcmdlZF93aWRlX2FsbCAgJT4lDQogIG11dGF0ZShHZW4gPSBhcy5mYWN0b3IoYXMuY2hhcmFjdGVyKEdlbikpKSAlPiUNCiAgbXV0YXRlKEdlbiA9IGZvcmNhdHM6OmZjdF9yZWNvZGUoR2VuLCAiZmVtaW4iID0gImYiLCAibWFzY3VsaW4iID0gIm0iKSkgJT4lDQogIGdyb3VwX2J5KEdlbikgJT4lDQogIGRwbHlyOjpzdW1tYXJpc2UoY291bnRzID0gbigpKQ0KDQojIHZhcnN0YQ0KRGF0YV9tZXJnZWRfd2lkZV9hbGwgJT4lDQogIG11dGF0ZShHZW4gPSBhcy5mYWN0b3IoYXMuY2hhcmFjdGVyKEdlbikpKSAlPiUNCiAgbXV0YXRlKFZhcnN0YSA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKFZhcnN0YSkpKSAlPiUNCiAgdGlkeXN0YXRzOjpkZXNjcmliZV9kYXRhKFZhcnN0YSwgbmEucm0gPSBUUlVFKQ0KDQojIHZhcnN0YSBieSBHZW4NCkRhdGFfbWVyZ2VkX3dpZGVfYWxsICU+JQ0KICBtdXRhdGUoVmFyc3RhID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoVmFyc3RhKSkpICU+JQ0KICBkcGx5cjo6Z3JvdXBfYnkoR2VuKSAlPiUNCiAgdGlkeXN0YXRzOjpkZXNjcmliZV9kYXRhKFZhcnN0YSwgbmEucm0gPSBUUlVFKSAlPiUNCiAga25pdHI6OmthYmxlKGNhcHRpb24gPSAiVmFyc3RhIGJ5IEdlbiIsIGZvcm1hdCA9ICJwYW5kb2MiLCBkaWdpdHMgPSAyKQ0KDQojIHQgdGVzdCB2YXJzdGEgYnkgR2VuDQpEYXRhX21lcmdlZF93aWRlX2FsbCAlPiUNCiAgbXV0YXRlKFZhcnN0YSA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKFZhcnN0YSkpKSAlPiUNCiAgdC50ZXN0KFZhcnN0YSB+IEdlbiwgZGF0YSA9IC4pICU+JSANCiAgdGlkeSgpDQpgYGANCg0KDQoNCiMgRGVmaW5lIEZ1bmN0aW9ucyANCg0KYGBge3IgZGVmX2Z1bmNfc3ViY2h1bmtwbG90LCBoaWRlPVRSVUV9DQpzdWJjaHVua2lmeSA8LSBmdW5jdGlvbihnLCBmaWdfaGVpZ2h0PTcsIGZpZ193aWR0aD01KSB7ICAgICAgICAjIFRISVMgRlVOQyBDUkFTSEVTIFBBTkRPQyBDT05WRVJTSU9OIFdJVEggRVJST1IgOTkgLSBET05UIFVTRSBIRVJFDQogIGdfZGVwYXJzZWQgPC0gcGFzdGUwKGRlcGFyc2UoDQogICAgZnVuY3Rpb24oKSB7Z30NCiAgKSwgY29sbGFwc2UgPSAnJykNCiAgDQogIHN1Yl9jaHVuayA8LSBwYXN0ZTAoIg0KICBgIiwiYGB7ciBzdWJfY2h1bmtfIiwgZmxvb3IocnVuaWYoMSkgKiAxMDAwMCksICIsIGZpZy5oZWlnaHQ9IiwgZmlnX2hlaWdodCwgIiwgZmlnLndpZHRoPSIsIGZpZ193aWR0aCwgIiwgZWNobz1GQUxTRX0iLA0KICAiXG4oIiwgDQogICAgZ19kZXBhcnNlZA0KICAgICwgIikoKSIsDQogICJcbmAiLCJgYA0KICAiKQ0KICANCiAgY2F0KGtuaXRyOjprbml0KHRleHQgPSBrbml0cjo6a25pdF9leHBhbmQodGV4dCA9IHN1Yl9jaHVuayksIHF1aWV0ID0gVFJVRSkpDQp9DQpgYGANCg0KYGBge3IgZGVmX2Z1bmNfY29yLCBoaWRlPVRSVUV9DQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQojIERlZmluZSBGdW5jdGlvbiBmb3IgbWluaW5nIGNvcnJlbGF0aW9ucw0KI35+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0KIyMgRnVuY3Rpb24gZm9yIHAtdmFsdWUgc2lnbmlmaWNhbmNlIC0tIGJvdGggZm9yIGZ1bmNfYW5jb3ZhX211bHRpYm94KCksIEdldF9Ub3BfUmVsYXRpb25zaGlwcygpIGFuZCBDb3JyZWxhdGlvbnNfV2l0aF9PbmUoKQ0Kc3RhcnNfc2lnbmlmIDwtIGZ1bmN0aW9uKHB2YWwpIHsNCiAgc3RhcnMgPSAibnMiDQogIGlmKHB2YWwgPD0gMC4wMDEpDQogICAgc3RhcnMgPSAiKioqIg0KICBpZihwdmFsID4gMC4wMDEgJiBwdmFsIDw9IDAuMDEpDQogICAgc3RhcnMgPSAiKioiDQogIGlmKHB2YWwgPiAwLjAxICYgcHZhbCA8PSAwLjA1KQ0KICAgIHN0YXJzID0gIioiDQogIGlmKHB2YWwgPiAwLjA1ICYgcHZhbCA8PSAwLjEpDQogICAgc3RhcnMgPSAiLiINCiAgc3RhcnMNCn0NCg0KIyMgRnVuY3Rpb24gdGhhdCByZXR1cm5zIGNvcnJlbGF0aW9ucyBvZiBhbGwgdmFyaWFibGVzIGluIGRlc2NlbmRpbmcgb3JkZXIuDQojIEFyZyBmb3IgdGhyZXNob2xkIHdpdGggZGVmYXVsdCBhdCAuMyB3aWxsIGtlZXAgb25seSBjb3JyZWxhbnRpb25zIGFib3ZlIC4zIGFuZCBiZWxvdyAtLjMuIEFsc28gaGFzIHRocmVzaGhvbGQgZm9yIHAtdmFsdWUuIA0KR2V0X1RvcF9SZWxhdGlvbnNoaXBzIDwtIGZ1bmN0aW9uKGRhdGFfc2V0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkPTAuMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsdWVfdGhyZXNob2xkPTAuMDUpIHsNCiAgcmVxdWlyZShwc3ljaCkNCiAgcmVxdWlyZShkcGx5cikNCiAgZmVhdHVyZV9uYW1lcyA8LSBuYW1lcyhkYXRhX3NldCkNCiAgIyBzdHJpcCB2YXIgbmFtZXMgdG8gaW5kZXggZm9yIHBhaXItd2lzZSBpZGVudGlmaWNhdGlvbg0KICBuYW1lcyhkYXRhX3NldCkgPC0gc2VxKDE6bmNvbChkYXRhX3NldCkpDQogICMgY2FsY3VsYXRlIGNvcnJlbGF0aW9uIGFuZCBzaWduaWZpY2FuY2UgbnVtYmVycw0KICBjb3JfZGF0YV9kZiA8LSBwc3ljaDo6Y29yci50ZXN0KGRhdGFfc2V0KQ0KICAjIGFwcGx5IHZhciBuYW1lcyB0byBjb3JyZWxhdGlvbiBtYXRyaXggb3ZlciBpbmRleA0KICByb3duYW1lcyhjb3JfZGF0YV9kZiRyKSA8LSBmZWF0dXJlX25hbWVzDQogIGNvbG5hbWVzKGNvcl9kYXRhX2RmJHIpIDwtIGZlYXR1cmVfbmFtZXMNCiAgIyB0b3AgY29yIGFuZCBzaWcNCiAgcmVsYXRpb25zaGlwc19zZXQgPC0gY29yX2RhdGFfZGYkY2lbLGMoJ3InLCdwJyldDQogICMgYXBwbHkgdmFyIG5hbWVzIHRvIGRhdGEgb3ZlciBpbmRleCBwYWlycw0KICByZWxhdGlvbnNoaXBzX3NldCRmZWF0dXJlXzEgPC0gZmVhdHVyZV9uYW1lc1thcy5udW1lcmljKHNhcHBseShzdHJzcGxpdChyb3duYW1lcyhyZWxhdGlvbnNoaXBzX3NldCksICItIiksIGBbYCwgMSkpXQ0KICByZWxhdGlvbnNoaXBzX3NldCRmZWF0dXJlXzIgPC0gZmVhdHVyZV9uYW1lc1thcy5udW1lcmljKA0KICAgIHNhcHBseShzdHJzcGxpdChyb3duYW1lcyhyZWxhdGlvbnNoaXBzX3NldCksICItIiksIGBbYCwgMikpXQ0KICByZWxhdGlvbnNoaXBzX3NldCA8LSBkcGx5cjo6c2VsZWN0KHJlbGF0aW9uc2hpcHNfc2V0LCBmZWF0dXJlXzEsIGZlYXR1cmVfMiwgciwgcCkgJT4lIGRwbHlyOjpyZW5hbWUoY29ycmVsYXRpb24gPSByLCBwLnZhbHVlID0gcCkNCiAgIyByZXR1cm4gb25seSB0aGUgbW9zdCBpbnN0ZXJlc3RpbmcgcmVsYXRpb25zaGlwcw0KICByZXR1cm4oZmlsdGVyKHJlbGF0aW9uc2hpcHNfc2V0LCBhYnMoY29ycmVsYXRpb24pID4gY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCAmDQogICAgICAgICAgICAgICAgICBwLnZhbHVlIDwgcHZhbHVlX3RocmVzaG9sZCkgJT4lIA0KICAgICAgICBhcnJhbmdlKHAudmFsdWUpICU+JQ0KICAgICAgICBtdXRhdGUocC5zaWduaWYgPSBzYXBwbHkocC52YWx1ZSwgZnVuY3Rpb24oeCkgc3RhcnNfc2lnbmlmKHgpKSkpDQp9DQoNCiMjIEZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhbGwgY29ycmVsYXRpb24gYmV0d2VlbiBudW1lcmljIHZhcmlhYmxlcyBhbmQgb25lIHNwZWNpZmljIHZhcmlhYmxlDQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUgPC0gZnVuY3Rpb24oZGF0YV9zZXQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZD0wLjMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlX3RocmVzaG9sZD0wLjA1KSB7DQogIHJlcXVpcmUocHN5Y2gpDQogIHJlcXVpcmUoZHBseXIpDQogICMgdXNlIGFsbCBudW1lcmljIGNvbHVtbnMgb25seQ0KICBudW1lcmljX2NvbHMgPC0gdW5saXN0KGxhcHBseShkYXRhX3NldCwgaXMubnVtZXJpYykpDQogIGRhdGFfc2V0IDwtIGRhdGFfc2V0WywgbnVtZXJpY19jb2xzXSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgIyBjYWxjdWxhdGUgY29ycmVsYXRpb24gYW5kIHNpZ25pZmljYW5jZSBudW1iZXJzDQogIGNvcl9kYXRhX2RmIDwtIHBzeWNoOjpjb3JyLnRlc3QoZGF0YV9zZXRbLCBuYW1lcyhkYXRhX3NldCkgIT0gdmFyaWFibGVdLCBkYXRhX3NldFssIHZhcmlhYmxlXSwgbWlubGVuZ3RoID0gMjAsIGFkanVzdD0ibm9uZSIpDQogICMgdG9wIGNvciBhbmQgc2lnDQogIHJlbGF0aW9uc2hpcHNfc2V0IDwtIGFzLmRhdGEuZnJhbWUoY2JpbmQoY29yX2RhdGFfZGYkciwgY29yX2RhdGFfZGYkcCkpICAgICAjIHNhbWUgYXMgIGNvcl9kYXRhX2RmJGNpWyxjKCdyJywncCcpXQ0KICByZWxhdGlvbnNoaXBzX3NldCA8LSB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbihyZWxhdGlvbnNoaXBzX3NldCwgIlZhcmlhYmxlIikgICAjIHJlbGF0aW9uc2hpcHNfc2V0JFZhcmlhYmxlIDwtIHJvd25hbWVzKHJlbGF0aW9uc2hpcHNfc2V0KQ0KICBjb2xuYW1lcyhyZWxhdGlvbnNoaXBzX3NldCkgPC0gYygiVmFyaWFibGUiLCAiY29ycmVsYXRpb24iLCAicC52YWx1ZSIpDQogICMgcmV0dXJuIG9ubHkgdGhlIG1vc3QgaW5zdGVyZXN0aW5nIHJlbGF0aW9uc2hpcHMNCiAgY2F0KCIjIyMjIENvcnJlbGF0aW9ucyB3aXRoICIsIHZhcmlhYmxlLCAiXG4iKQ0KICByZXR1cm4oZmlsdGVyKHJlbGF0aW9uc2hpcHNfc2V0LCBhYnMoY29ycmVsYXRpb24pID4gY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCAmDQogICAgICAgICAgICAgICAgICBwLnZhbHVlIDwgcHZhbHVlX3RocmVzaG9sZCkgJT4lIA0KICAgICAgICAgICBhcnJhbmdlKHAudmFsdWUpICU+JQ0KICAgICAgICAgICBtdXRhdGUocC5zaWduaWYgPSBzYXBwbHkocC52YWx1ZSwgZnVuY3Rpb24oeCkgc3RhcnNfc2lnbmlmKHgpKSkpICU+JQ0KICAgICAgICAgICB0aWJibGU6OmFzLnRpYmJsZSgpDQp9ICANCg0KDQojIyBGdW5jdGlvbiBmb3IgcGxvdGluZyBjb3JyZWxhdGlvbiBkYXRhIGZyYW1lcyByZXN1bHRpbmcgZnJvbSBHZXRfVG9wX1JlbGF0aW9uc2hpcHMgYW5kIENvcnJlbGF0aW9uc19XaXRoX09uZSgpDQpmdW5jX2RvdHBsb3RfY29yIDwtIGZ1bmN0aW9uKGRmKXsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBodHRwczovL3d3dy5yLXBrZy5vcmcvcGtnL2dncHVicg0KICBkb3RwbG90Y29yX3NjYWxlX2ZpbGwgPC0gZnVuY3Rpb24oLi4uKXsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgRml4IGNvbG9ycyB0byBzaWduaWYgZmFjdG9yIGxldmVscyBldmVuIGlmIG1pc3NpbmcNCiAgICBnZ3Bsb3QyOjo6bWFudWFsX3NjYWxlKCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAnY29sb3InLCANCiAgICAgIHZhbHVlcyA9IHNldE5hbWVzKA0KICAgICAgICBjKCJkYXJrZ3JlZW4iLCAiZ3JlZW4zIiwgImxhd25ncmVlbiIsICJ5ZWxsb3ciLCAicmVkIiksIA0KICAgICAgICBjKCIqKioiLCAiKioiLCAiKiIsICIuIiwgIm5zIikpLCANCiAgICAgIC4uLg0KICAgICkNCiAgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgDQogIGR0b3Bsb3RfdGhlbWUgPC0gDQogICAgZ2dwdWJyOjp0aGVtZV9wdWJyKCkgKw0KICAgIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpDQogIA0KICBpZighIlZhcmlhYmxlIiAlaW4lIGNvbG5hbWVzKGRmKSl7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbiBvZGVyIHRvIHdvcmsgZm9yIGJvdGggR2V0X1RvcF9SZWxhdGlvbnNoaXBzIGFuZCBDb3JyZWxhdGlvbnNfV2l0aF9PbmUoKQ0KICBkZiA8LSANCiAgICBkZiAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgdW5pdGUoY29yX2JldHdlZW4sIGMoImZlYXR1cmVfMSIsICJmZWF0dXJlXzIiKSwgc2VwID0gIiBYICIpICAgICAgICAgICAgICAgIyB1bml0ZSAyIGNvbHVtbnMgdG8geCBuYW1lIGZyb20gcGxvdA0KICB9ZWxzZSBkZiA8LSBkZiAlPiUgZHBseXI6OnJlbmFtZShjb3JfYmV0d2VlbiA9IFZhcmlhYmxlKSAgICAgICAgICAgICAgICAgICAgICAgIyBjaGFuZ2UgVmFyaWFibGUgdG8geCBuYW1lIGZyb20gcGxvdA0KICANCiAgZGYgJT4lDQogICAgZ2dwdWJyOjpnZ2RvdGNoYXJ0KHggPSAiY29yX2JldHdlZW4iLCB5ID0gImNvcnJlbGF0aW9uIiwNCiAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAicC5zaWduaWYiLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgQ29sb3IgYnkgc2lnDQogICAgICAgICAgICAgICAgICAgICAgICMgICBwYWxldHRlID0gYygiIzAwQUZCQiIsICIjRTdCODAwIiwgIiNGQzRFMDciKSwgICAgICAgICAjIEN1c3RvbSBjb2xvciBwYWxldHRlDQogICAgICAgICAgICAgICAgICAgICAgIHNvcnRpbmcgPSAiZGVzY2VuZGluZyIsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFNvcnQgdmFsdWUgaW4gZGVzY2VuZGluZyBvcmRlcg0KICAgICAgICAgICAgICAgICAgICAgICBhZGQgPSAic2VnbWVudHMiLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBBZGQgc2VnbWVudHMgZnJvbSB5ID0gMCB0byBkb3RzDQogICAgICAgICAgICAgICAgICAgICAgIGFkZC5wYXJhbXMgPSBsaXN0KGNvbG9yID0gImxpZ2h0Z3JheSIsIHNpemUgPSAyKSwgICAgICAgICAjIENoYW5nZSBzZWdtZW50IGNvbG9yIGFuZCBzaXplDQogICAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gInAuc2lnbmlmIiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIE9yZGVyIGJ5IGdyb3Vwcw0KICAgICAgICAgICAgICAgICAgICAgICBkb3Quc2l6ZSA9IDgsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBMYXJnZSBkb3Qgc2l6ZQ0KICAgICAgICAgICAgICAgICAgICAgICB4bGFiID0gIiIsDQogICAgICAgICAgICAgICAgICAgICAgIHJvdGF0ZSA9IFRSVUUsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFJvdGF0ZSB2ZXJ0aWNhbGx5DQogICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gcm91bmQoLiRjb3JyZWxhdGlvbiwgMSksICAgICAgICAgICAgICAgICAgICAgICAgICAjIEFkZCBtcGcgdmFsdWVzIGFzIGRvdCBsYWJlbHMNCiAgICAgICAgICAgICAgICAgICAgICAgZm9udC5sYWJlbCA9IGxpc3QoY29sb3IgPSAid2hpdGUiLCBzaXplID0gOSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZqdXN0ID0gMC41KSwgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEFkanVzdCBsYWJlbCBwYXJhbWV0ZXJzDQogICAgICAgICAgICAgICAgICAgICAgIGdndGhlbWUgPSBkdG9wbG90X3RoZW1lKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGdncGxvdDIgdGhlbWUNCiAgICBkb3RwbG90Y29yX3NjYWxlX2ZpbGwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEZpeCBjb2xvcnMgdG8gc2lnbmlmIGZhY3RvciBsZXZlbHMgZXZlbiBpZiBtaXNzaW5nDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBjb2xvciA9ICJsaWdodGdyYXkiKQ0KfQ0KYGBgDQoNCmBgYHtyIGRlZl9mdW5jX21lYW5jb21wLCBoaWRlPVRSVUV9DQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQojIERlZmluZSBGdW5jdGlvbiBmb3IgUHJlLVBvc3QgUGxvdHMsIHQgQ2hhbmdlIGFuZCBBTkNPVkEgUG9zdA0KI35+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0KIyMgRnVuYyB0IHRlc3Qgc2kgYm94cGxvdCBzaW1wbHUNCmZ1bmNfdF9ib3ggPC0gZnVuY3Rpb24oZGYsIGluZCwgcHJlX3ZhciwgcG9zdF92YXIpew0KICBkZl9tb2RpZiA8LQ0KICAgIGRmICU+JQ0KICAgIHNlbGVjdChpbmQsIHByZV92YXIsIHBvc3RfdmFyKSAlPiUgDQogICAgdGlkeXI6OmRyb3BfbmEoKSAlPiUNCiAgICBnYXRoZXIocHJlX3ZhciwgcG9zdF92YXIsIGtleSA9ICJDb25kIiwgdmFsdWUgPSAidmFsdWUiKSAlPiUgDQogICAgbXV0YXRlX2F0KHZhcnMoYygxLCAyKSksIGxpc3QofmFzLmZhY3RvciguKSkpICU+JSANCiAgICBtdXRhdGUoQ29uZCA9IGZhY3RvcihDb25kLCBsZXZlbHMgPSBjKHByZV92YXIsIHBvc3RfdmFyKSkpIA0KICANCiAgc3RhdF9jb21wIDwtIGdncHVicjo6Y29tcGFyZV9tZWFucyh2YWx1ZSB+IENvbmQsIGRhdGEgPSBkZl9tb2RpZiwgbWV0aG9kID0gInQudGVzdCIsIHBhaXJlZCA9IFRSVUUpDQogIA0KICBzdGF0X2NvbXAyIDwtDQogICAgZGZfbW9kaWYgJT4lIA0KICAgIGRvKHRpZHkodC50ZXN0KC4kdmFsdWUgfiAuJENvbmQsDQogICAgICAgICAgICAgICAgICAgcGFpcmVkID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICBkYXRhPS4pKSkNCiAgDQogIHBsb3QgPC0gDQogICAgZ2dwdWJyOjpnZ3BhaXJlZChkZl9tb2RpZiwgeCA9ICJDb25kIiwgeSA9ICJ2YWx1ZSIsIGlkID0gaW5kLCANCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIkNvbmQiLCBsaW5lLmNvbG9yID0gImdyYXkiLCBsaW5lLnNpemUgPSAwLjQsDQogICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gYygiIzAwQUZCQiIsICIjRkM0RTA3IiksIGxlZ2VuZCA9ICJub25lIikgKw0KICAgICAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9zZSwgIGNvbG91ciA9ICJkYXJrcmVkIikgKw0KICAgICAgZ2dwdWJyOjpzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gInQudGVzdCIsIHBhaXJlZCA9IFRSVUUsIGxhYmVsLnggPSBhcy5udW1lcmljKGRmX21vZGlmJENvbmQpLTAuNCwgbGFiZWwueSA9IG1heChkZl9tb2RpZiR2YWx1ZSkrMC41KSArIA0KICAgICAgZ2dwdWJyOjpzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gInQudGVzdCIsIHBhaXJlZCA9IFRSVUUsIGxhYmVsID0gInAuc2lnbmlmIiwgY29tcGFyaXNvbnMgPSBsaXN0KGMocHJlX3ZhciwgcG9zdF92YXIpKSkNCiAgDQogIGNhdChwYXN0ZTAoIiMjIyMgIiwgcHJlX3ZhciwgIiAiLCBwb3N0X3ZhciwgIlxuIiwgIlxuIikpDQogIHByaW50KHN0YXRfY29tcCkNCiAgcHJpbnQoc3RhdF9jb21wMikNCiAgcHJpbnQocGxvdCkNCn0NCg0KDQpmdW5jX2FuY292YV9tdWx0aWJveCA8LSBmdW5jdGlvbihkZiwgaW5kLCBwcmVfdmFyX2MxLCBwb3N0X3Zhcl9jMSwgcHJlX3Zhcl9jMiwgcG9zdF92YXJfYzIpew0KICANCiAgZGlmZl9zY29yZV9jMSA8LSBwYXN0ZTAocG9zdF92YXJfYzEsICIgLSAiLCBwcmVfdmFyX2MxKQ0KICBkaWZmX3Njb3JlX2MyIDwtIHBhc3RlMChwb3N0X3Zhcl9jMiwgIiAtICIsIHByZV92YXJfYzIpDQogIA0KICAjIyBQbG90cyBhbmQgcC12YWx1ZXMgZm9yIHQgdGVzdHMNCiAgZGZfbW9kaWYgPC0NCiAgICBkZiAlPiUNCiAgICBzZWxlY3QoaW5kLCBwcmVfdmFyX2MxLCBwb3N0X3Zhcl9jMSwgcHJlX3Zhcl9jMiwgcG9zdF92YXJfYzIpICU+JSANCiAgICB0aWR5cjo6ZHJvcF9uYSgpICU+JQ0KICAgIGdhdGhlcihwcmVfdmFyX2MxLCBwb3N0X3Zhcl9jMSwgcHJlX3Zhcl9jMiwgcG9zdF92YXJfYzIsIGtleSA9ICJDb25kIiwgdmFsdWUgPSAidmFsdWUiKSAlPiUgDQogICAgbXV0YXRlX2F0KHZhcnMoYygxLCAyKSksIGxpc3QofmFzLmZhY3RvciguKSkpICU+JSANCiAgICBtdXRhdGUoQ29uZCA9IGZhY3RvcihDb25kLCBsZXZlbHMgPSBjKHByZV92YXJfYzEsIHBvc3RfdmFyX2MxLCBwcmVfdmFyX2MyLCBwb3N0X3Zhcl9jMikpKSANCiAgDQogIHN0YXRfY29tcCA8LSBnZ3B1YnI6OmNvbXBhcmVfbWVhbnModmFsdWUgfiBDb25kLCBkYXRhID0gZGZfbW9kaWYsIG1ldGhvZCA9ICJ0LnRlc3QiLCBwYWlyZWQgPSBUUlVFLCBwLmFkanVzdC5tZXRob2QgPSAiaG9sbSIpDQogIA0KICBwbG90IDwtDQogICAgZ2dwdWJyOjpnZ3BhaXJlZChkZl9tb2RpZiwgeCA9ICJDb25kIiwgeSA9ICJ2YWx1ZSIsIGlkID0gaW5kLCANCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIkNvbmQiLCBsaW5lLmNvbG9yID0gImdyYXkiLCBsaW5lLnNpemUgPSAwLjQsDQogICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gYygiIzAwQUZCQiIsICIjRkM0RTA3IiwgIiMwMEFGQkIiLCAiI0ZDNEUwNyIpLCBsZWdlbmQgPSAibm9uZSIpICsNCiAgICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX3NlLCAgY29sb3VyID0gImRhcmtyZWQiKSArDQogICAgZ2dwdWJyOjpzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gInQudGVzdCIsIHBhaXJlZCA9IFRSVUUsIGxhYmVsID0gInAuc2lnbmlmIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwueSA9IGMobWF4KGRmX21vZGlmJHZhbHVlKSArIDAuMSpJUVIoZGZfbW9kaWYkdmFsdWUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChkZl9tb2RpZiR2YWx1ZSkgKyAwLjEqSVFSKGRmX21vZGlmJHZhbHVlKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXEobWF4KGRmX21vZGlmJHZhbHVlKSArIDAuMypJUVIoZGZfbW9kaWYkdmFsdWUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGRmX21vZGlmJHZhbHVlKSArIDAuOSpJUVIoZGZfbW9kaWYkdmFsdWUpLCBsZW5ndGgub3V0ID0gNCkpLCAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcGFyaXNvbnMgPSBsaXN0KGMocHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKHByZV92YXJfYzIsIHBvc3RfdmFyX2MyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYyhwb3N0X3Zhcl9jMSwgcHJlX3Zhcl9jMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMocHJlX3Zhcl9jMSwgcHJlX3Zhcl9jMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMocG9zdF92YXJfYzEsIHBvc3RfdmFyX2MyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYyhwcmVfdmFyX2MxLCBwb3N0X3Zhcl9jMikpKQ0KICANCiAgIyMgRm9yIHR0ZXN0Q2hhbmdlIG9yIEFOQ09WQUNoYW5nZSAtIHdlIGRvIHR0ZXN0Q2hhbmdlIChQb3N0LVByZSkgaGVyZSwgYnV0IGl0IGlzbnQgdmVyeSBpbXBvcnRhbnQNCiAgZGZfbW9kaWYyIDwtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgZGYgJT4lDQogICAgc2VsZWN0KGluZCwgcHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEsIHByZV92YXJfYzIsIHBvc3RfdmFyX2MyKSAlPiUNCiAgICB0aWR5cjo6ZHJvcF9uYSgpIA0KICBkZl9tb2RpZjJbZGlmZl9zY29yZV9jMV0gPC0gZGZfbW9kaWYyWywgcG9zdF92YXJfYzFdIC0gZGZfbW9kaWYyWywgcHJlX3Zhcl9jMV0NCiAgZGZfbW9kaWYyW2RpZmZfc2NvcmVfYzJdIDwtIGRmX21vZGlmMlssIHBvc3RfdmFyX2MyXSAtIGRmX21vZGlmMlssIHByZV92YXJfYzJdDQogIA0KICB0Q2hhbmdlIDwtIHQudGVzdChkZl9tb2RpZjJbLCBkaWZmX3Njb3JlX2MxXSwgZGZfbW9kaWYyWywgZGlmZl9zY29yZV9jMl0sIHBhaXJlZCA9IFRSVUUpDQogIA0KICAjIyBGb3IgZGVzY3JpcHRpdmVzIGJ5IDIgZmFjdG9ycyAoUHJlUG9zdCBhbmQgT2dsRWNyYW4pDQogIGRmX21vZGlmMyA8LQ0KICAgIGRmICU+JQ0KICAgIHNlbGVjdChpbmQsIHByZV92YXJfYzEsIHBvc3RfdmFyX2MxLCBwcmVfdmFyX2MyLCBwb3N0X3Zhcl9jMikgJT4lDQogICAgdGlkeXI6OmRyb3BfbmEoKSAlPiUNCiAgICBnYXRoZXIocHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEsIHByZV92YXJfYzIsIHBvc3RfdmFyX2MyLCBrZXkgPSAiQ29uZCIsIHZhbHVlID0gInZhbHVlIikgJT4lDQogICAgbXV0YXRlKFByZVBvc3QgPSBjYXNlX3doZW4oc3RyaW5ncjo6c3RyX2RldGVjdCguJCJDb25kIiwgInByZXxQcmUiKSB+ICJQcmUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3I6OnN0cl9kZXRlY3QoLiQiQ29uZCIsICJwb3N0fFBvc3QiKSB+ICJQb3N0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXyksDQogICAgICAgICAgIE9nbEVjcmFuID0gY2FzZV93aGVuKHN0cmluZ3I6OnN0cl9kZXRlY3QoLiQiQ29uZCIsICJvZ2x8T0dMIikgfiAiT0dMIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3I6OnN0cl9kZXRlY3QoLiQiQ29uZCIsICJlY3JhbnxFQ1JBTiIpIH4gIkVDUkFOIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfKSkgJT4lDQogICAgbXV0YXRlKFByZVBvc3QgPSBhcy5mYWN0b3IoUHJlUG9zdCksDQogICAgICAgICAgIE9nbEVjcmFuID0gYXMuZmFjdG9yKE9nbEVjcmFuKSkNCiAgDQogICMjIEZvciBBTkNPVkFQb3N0IC0gdGhpcyBpcyB3aGF0IHdlIHVzZQ0KICBkZl9tb2RpZjQgPC0NCiAgICBkZl9tb2RpZjMgJT4lDQogICAgc2VsZWN0KC0iQ29uZCIpICU+JQ0KICAgIHNwcmVhZCgiUHJlUG9zdCIsICJ2YWx1ZSIpDQogIA0KICAjIyBNb2RlbHMgKGhlcmUgd2UgdXNlIEFOQ09WQVBvc3QpICAgICMgaHR0cHM6Ly9tLWNsYXJrLmdpdGh1Yi5pby9kb2NzL21peGVkTW9kZWxzL2Fub3ZhbWl4ZWQuaHRtbCNpbnRyb2R1Y3Rpb24NCiAgZnVsbF9hbmNvdmFQb3N0IDwtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGlzIGlzIGJldHRlciB0aGFuIHVzaW5nIGxtKCkgYW5kIGdsaHQoKQ0KICAgICAgam12OjphbmNvdmEoDQogICAgICAgIGZvcm11bGEgPSBQb3N0IH4gUHJlICsgT2dsRWNyYW4sDQogICAgICAgIGRhdGEgPSBkZl9tb2RpZjQsDQogICAgICAgIGhvbW8gPSBUUlVFLA0KICAgICAgICBzcyA9ICIzIiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICBwb3N0SG9jID0gfiBPZ2xFY3JhbiwNCiAgICAgICAgcG9zdEhvY0NvcnIgPSBsaXN0KCJ0dWtleSIpLA0KICAgICAgICBlZmZlY3RTaXplID0gbGlzdCgiZXRhIiwgInBhcnRFdGEiKQ0KICAgICAgKQ0KICANCiAgICAgICMgbW9kX2FuY292YVBvc3QgPC0gbG0oUG9zdCB+IFByZSArIE9nbEVjcmFuLCBkYXRhID0gZGZfbW9kaWY0KSAgICAgICAgICAgICMgdGhpcyBpcyBhIENvdmFyaWF0ZSBTZWNvbmQgbW9kZWwNCiAgICAgICMgbW9kX2FuY292YVBvc3Rfc3MzIDwtIGNhcjo6QW5vdmEobW9kX2FuY292YVBvc3QsIHR5cGUgPSAiSUlJIikgICAgICAgICAjIFR5cGUgSUlJIHN1bXMgb2Ygc3F1YXJlczsgc2VlIEFuZHkgRmllbGRzIDIwMTINCiAgICAgICMgcG9zdEhvY3MgPC0gbXVsdGNvbXA6OmdsaHQobW9kX2FuY292YVBvc3QsIGxpbmZjdCA9IG11bHRjb21wOjptY3AoT2dsRWNyYW4gPSAiVHVrZXkiKSkgICMgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgYWRqdXN0ZWQgbWVhbnMsDQogICAgICAjIHN1bV9wb3N0SG9jcyA8LSBzdW1tYXJ5KHBvc3RIb2NzKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB1c2UgVHVrZXkgb3IgRHVubmV0dD9zIHBvc3QgaG9jIHRlc3RzDQogICAgICAjIGNvbmZfcG9zdEhvY3MgPC0gY29uZmludChwb3N0SG9jcykNCiAgc2NhdHRlciA8LSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIENoZWNrIGZvciBob21vZ2VuZWl0eSBvZiByZWdyZXNzaW9uIHNsb3Blcw0KICAgIGdncGxvdChkZl9tb2RpZjQsIGFlcyhQcmUsIFBvc3QsIGNvbG91ciA9IE9nbEVjcmFuKSkgKw0KICAgIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gT2dsRWNyYW4pLCBzaXplID0gMykgKw0KICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGFlcyhmaWxsID0gT2dsRWNyYW4pLCBhbHBoYSA9IDAuMSkNCiAgICANCiAgDQogICMjIE90aGVyIE1vZGVscyB0aGF0IHdvcmsgZm9yIHRoaXMgZGF0ZQ0KICAjIG1vZF9hbmNvdmFQb3N0IDwtIGxtKHBvc3QgfiBwcmUgKyB0cmVhdCkgICAgICAjIGV4YWN0bHkgdGhlIHNhbWUgd2l0aCBhb3YocG9zdCB+IHByZSArIHRyZWF0KQ0KICAjIHN1bW1hcnkobW9kX2FuY292YVBvc3QpDQogICMgDQogICMgbW9kX2Fub3ZhUk0gPC0gYW92KHNjb3JlIH4gdHJlYXQqdGltZSArIEVycm9yKGlkKSwgZGZsb25nKQ0KICAjIHN1bW1hcnkobW9kX2Fub3ZhUk0pDQogICMgDQogICMgbW9kX2xtZSA8LSBsbWU0OjpsbWVyKHNjb3JlIH4gdHJlYXQqdGltZSArICgxfGlkKSwgZGF0YT1kZmxvbmcpDQogICMgYW5vdmEobG1lTW9kZWwpDQogIA0KICAjIyBPdXRwdXQNCiAgcHJpbnQocGxvdCkNCiAgY2F0KHBhc3RlMCgiIyMjIyAiLCBwcmVfdmFyX2MxLCAiICIsIHBvc3RfdmFyX2MxLCAiICIsIHByZV92YXJfYzIsICIgIiwgcG9zdF92YXJfYzIsICJcbiIsICJcbiIpKQ0KICANCiAgY2F0KCIjIyMjIERlc2NyaXB0aXZlcyIpDQogIHBzeWNoOjpkZXNjcmliZUJ5KGRmX21vZGlmM1ssICJ2YWx1ZSJdLCBsaXN0KGRmX21vZGlmM1ssICJQcmVQb3N0Il0sIGRmX21vZGlmM1ssICJPZ2xFY3JhbiJdKSwgbWF0ID0gVFJVRSkgJT4lIA0KICAgIGFzLnRpYmJsZSgpICU+JQ0KICAgIHByaW50KCkNCiAgY2F0KCJcbiIpDQogIA0KICBwcmludChzdGF0X2NvbXApDQogIGNhdCgiXG4iKQ0KICANCiAgY2F0KCIjIyMjIHQgQ2hhbmdlIikNCiAgdGlkeSh0Q2hhbmdlKSAlPiUgcHJpbnQoKQ0KICBjYXQoIlxuIikNCiAgDQogIGNhdCgiIyMjIyBBTkNPVkEgUG9zdCIpDQogIGNhdCgiXG4iKQ0KICBjYXQoIiMjIyMjIEhvbW9nZW5laXR5IHRlc3QiKQ0KICBwcmludCh0aWJibGU6OmFzLnRpYmJsZShmdWxsX2FuY292YVBvc3QkYXNzdW1wJGhvbW8pKQ0KICBjYXQoIiMjIyMjIEFOQ09WQSBvdXRwdXQiKQ0KICBwcmludCh0aWJibGU6OmFzLnRpYmJsZShmdWxsX2FuY292YVBvc3QkbWFpbikpDQogICMgdGlkeShtb2RfYW5jb3ZhUG9zdCkgJT4lIA0KICAjICAgbXV0YXRlKHAuc2lnbmlmID0gc2FwcGx5KHAudmFsdWUsIGZ1bmN0aW9uKHgpIHN0YXJzX3NpZ25pZih4KSkpICU+JSANCiAgIyAgIHByaW50KCkNCiAgIyBjYXQoIlxuIikNCiAgY2F0KCIjIyMjIyBQb3N0IEhvYyIpDQogIHByaW50KHRpYmJsZTo6YXMudGliYmxlKGZ1bGxfYW5jb3ZhUG9zdCRwb3N0SG9jW1sxXV0pKQ0KICAjIHRpZHkoc3VtX3Bvc3RIb2NzKSAlPiUgDQogICMgICBtdXRhdGUocC5zaWduaWYgPSBzYXBwbHkocC52YWx1ZSwgZnVuY3Rpb24oeCkgc3RhcnNfc2lnbmlmKHgpKSkgJT4lIA0KICAjICAgcHJpbnQoKQ0KICBjYXQoIlxuIikNCiAgY2F0KCIjIyMjIyBIb21vZ2VuZWl0eSBvZiByZWdyZXNzaW9uIHNsb3BlcyIpDQogICMgc3ViY2h1bmtpZnkocGxvdChzY2F0dGVyKSwgNSwgNSkgICAgICAgICAgICAgICAgICAgICAgICMgVEhJUyBGVU5DIENSQVNIRVMgUEFORE9DIENPTlZFUlNJT04gV0lUSCBFUlJPUiA5OSAtIERPTlQgVVNFIEhFUkUNCn0NCmBgYA0KDQoNCg0KIyBBbmFseXNlcw0KDQojIyBTaW1wbGUgYmVmb3JlLWFmdGVyIGFuYWx5c2VzIHdpdGggdCB0ZXN0DQoNCmBgYHtyIHRfdGVzdCwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NywgcmVzdWx0cz0nYXNpcyd9DQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQojIFNpbXBsZSBiZWZvcmUtYWZ0ZXIgYW5hbHlzZXMgd2l0aCB0IHRlc3QNCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiMjIE9YVCBoYXMgMiBvdXRsaWVyczogMTksIDQzDQojIGZ1bmNfdF9ib3goRGF0YV9tZXJnZWRfd2lkZSwgIklEIiwgIk9YVF9QcmVfT0dMIiwgIk9YVF9Qb3N0X09HTCIpICAgICAgICAgICMgb3V0bGllciBpbiA1NyBzdWIgIA0KIyBmdW5jX3RfYm94KERhdGFfbWVyZ2VkX3dpZGUsICJJRCIsICJPWFRfUHJlX0VDUkFOIiwgIk9YVF9Qb3N0X0VDUkFOIikgICAgICAjIG5zDQoNCmZ1bmNfdF9ib3goRGF0YV9tZXJnZWRfd2lkZV9hbGwsICJJRCIsICJPWFRfUHJlX09HTCIsICJPWFRfUG9zdF9PR0wiKSAgICAjIG5zDQpmdW5jX3RfYm94KERhdGFfbWVyZ2VkX3dpZGVfYWxsLCAiSUQiLCAiT1hUX1ByZV9FQ1JBTiIsICJPWFRfUG9zdF9FQ1JBTiIpICAgIyBucw0KDQpmdW5jX3RfYm94KERhdGFfbWVyZ2VkX3dpZGVfYWxsLCAiSUQiLCAiVmFzX1N0cmVzX1ByZV9PR0wiLCAiVmFzX1N0cmVzX1Bvc3RfT0dMIikgICAgICAgICAjIHNpZyAgDQpmdW5jX3RfYm94KERhdGFfbWVyZ2VkX3dpZGVfYWxsLCAiSUQiLCAiVmFzX1N0cmVzX1ByZV9FQ1JBTiIsICJWYXNfU3RyZXNfUG9zdF9FQ1JBTiIpICAgICAjIG5zDQoNCmZ1bmNfdF9ib3goRGF0YV9tZXJnZWRfd2lkZV9hbGwsICJJRCIsICJWYXNfQmluZV9QcmVfT0dMIiwgIlZhc19CaW5lX1Bvc3RfT0dMIikgICAgICAgICAgICMgbnMgIA0KZnVuY190X2JveChEYXRhX21lcmdlZF93aWRlX2FsbCwgIklEIiwgIlZhc19CaW5lX1ByZV9FQ1JBTiIsICJWYXNfQmluZV9Qb3N0X0VDUkFOIikgICAgICAgIyBzaWcNCg0KZnVuY190X2JveChEYXRhX21lcmdlZF93aWRlX2FsbCwgIklEIiwgIklPU19QcmVfT0dMIiwgIklPU19Qb3N0X09HTCIpICAgICAgICAgICAgICAgICAgICAgIyBzaWcgIA0KZnVuY190X2JveChEYXRhX21lcmdlZF93aWRlX2FsbCwgIklEIiwgIklPU19QcmVfRUNSQU4iLCAiSU9TX1Bvc3RfRUNSQU4iKSAgICAgICAgICAgICAgICAgIyBucw0KYGBgDQoNCg0KIyMgdENoYW5jZSBhbmQgQU5DT1ZBUG9zdA0KDQpgYGB7ciB0X0NoYW5nZV9BTkNPVkFfUG9zdHMsIGZpZy53aWR0aD0xMSwgZmlnLmhlaWdodD0xMiwgcmVzdWx0cz0nYXNpcyd9DQojIyB0Q2hhbmNlIGFuZCBBTkNPVkFQb3N0IA0KDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhX21lcmdlZF93aWRlX2FsbCwgIklEIiwgIk9YVF9QcmVfT0dMIiwgIk9YVF9Qb3N0X09HTCIsICJPWFRfUHJlX0VDUkFOIiwgIk9YVF9Qb3N0X0VDUkFOIikgICAgICAgICAgICAgICMgbnMNCg0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YV9tZXJnZWRfd2lkZV9hbGwsICAiSUQiLCAiVmFzX1N0cmVzX1ByZV9PR0wiLCAiVmFzX1N0cmVzX1Bvc3RfT0dMIiwgIlZhc19TdHJlc19QcmVfRUNSQU4iLCAiVmFzX1N0cmVzX1Bvc3RfRUNSQU4iKSAgICAjIG5zDQoNCmZ1bmNfYW5jb3ZhX211bHRpYm94KERhdGFfbWVyZ2VkX3dpZGVfYWxsLCAgIklEIiwgIlZhc19CaW5lX1ByZV9PR0wiLCAiVmFzX0JpbmVfUG9zdF9PR0wiLCAiVmFzX0JpbmVfUHJlX0VDUkFOIiwgIlZhc19CaW5lX1Bvc3RfRUNSQU4iKSAgICAgICAgIyBucw0KDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhX21lcmdlZF93aWRlX2FsbCwgICJJRCIsICJJT1NfUHJlX09HTCIsICJJT1NfUG9zdF9PR0wiLCAiSU9TX1ByZV9FQ1JBTiIsICJJT1NfUG9zdF9FQ1JBTiIpICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgc2lnDQoNCmBgYA0KDQoNCiMjIFNpbXBsZSBiZWZvcmUtYWZ0ZXIgYW5hbHlzZXMgd2l0aCB0IHRlc3QgYnkgR2VuZGVyDQoNCmBgYHtyIHRfdGVzdF9nZW4sIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTcsIHJlc3VsdHM9J2FzaXMnfQ0KIyBGZW1hbGVzDQpjYXQoIiMjIyBGZW0iKQ0KZnVuY190X2JveChEYXRhX2ZlbSwgIklEIiwgIk9YVF9QcmVfT0dMIiwgIk9YVF9Qb3N0X09HTCIpICAgICMgc2lnDQpmdW5jX3RfYm94KERhdGFfZmVtLCAiSUQiLCAiT1hUX1ByZV9FQ1JBTiIsICJPWFRfUG9zdF9FQ1JBTiIpICAgIyBucw0KDQpmdW5jX3RfYm94KERhdGFfZmVtLCAiSUQiLCAiVmFzX1N0cmVzX1ByZV9PR0wiLCAiVmFzX1N0cmVzX1Bvc3RfT0dMIikgICAgICAgICAjIHNpZyANCmZ1bmNfdF9ib3goRGF0YV9mZW0sICJJRCIsICJWYXNfU3RyZXNfUHJlX0VDUkFOIiwgIlZhc19TdHJlc19Qb3N0X0VDUkFOIikgICAgICMgc2lnDQoNCmZ1bmNfdF9ib3goRGF0YV9mZW0sICJJRCIsICJWYXNfQmluZV9QcmVfT0dMIiwgIlZhc19CaW5lX1Bvc3RfT0dMIikgICAgICAgICAgICMgbnMgIA0KZnVuY190X2JveChEYXRhX2ZlbSwgIklEIiwgIlZhc19CaW5lX1ByZV9FQ1JBTiIsICJWYXNfQmluZV9Qb3N0X0VDUkFOIikgICAgICAgIyBucw0KDQpmdW5jX3RfYm94KERhdGFfZmVtLCAiSUQiLCAiSU9TX1ByZV9PR0wiLCAiSU9TX1Bvc3RfT0dMIikgICAgICAgICAgICAgICAgICAgICAjIHNpZyAgDQpmdW5jX3RfYm94KERhdGFfZmVtLCAiSUQiLCAiSU9TX1ByZV9FQ1JBTiIsICJJT1NfUG9zdF9FQ1JBTiIpICAgICAgICAgICAgICAgICAjIG5zDQoNCiMgTWFsZXMNCmNhdCgiIyMjIE1hc2MiKQ0KZnVuY190X2JveChEYXRhX21hc2MsICJJRCIsICJPWFRfUHJlX09HTCIsICJPWFRfUG9zdF9PR0wiKSAgICAjIG5zDQpmdW5jX3RfYm94KERhdGFfbWFzYywgIklEIiwgIk9YVF9QcmVfRUNSQU4iLCAiT1hUX1Bvc3RfRUNSQU4iKSAgICMgbnMNCg0KZnVuY190X2JveChEYXRhX21hc2MsICJJRCIsICJWYXNfU3RyZXNfUHJlX09HTCIsICJWYXNfU3RyZXNfUG9zdF9PR0wiKSAgICAgICAgICMgbnMgIA0KZnVuY190X2JveChEYXRhX21hc2MsICJJRCIsICJWYXNfU3RyZXNfUHJlX0VDUkFOIiwgIlZhc19TdHJlc19Qb3N0X0VDUkFOIikgICAgICMgbnMNCg0KZnVuY190X2JveChEYXRhX21hc2MsICJJRCIsICJWYXNfQmluZV9QcmVfT0dMIiwgIlZhc19CaW5lX1Bvc3RfT0dMIikgICAgICAgICAgICMgbnMgIA0KZnVuY190X2JveChEYXRhX21hc2MsICJJRCIsICJWYXNfQmluZV9QcmVfRUNSQU4iLCAiVmFzX0JpbmVfUG9zdF9FQ1JBTiIpICAgICAgICMgbnMNCg0KZnVuY190X2JveChEYXRhX21hc2MsICJJRCIsICJJT1NfUHJlX09HTCIsICJJT1NfUG9zdF9PR0wiKSAgICAgICAgICAgICAgICAgICAgICMgc2lnICANCmZ1bmNfdF9ib3goRGF0YV9tYXNjLCAiSUQiLCAiSU9TX1ByZV9FQ1JBTiIsICJJT1NfUG9zdF9FQ1JBTiIpICAgICAgICAgICAgICAgICAjIG5zDQpgYGANCg0KDQojIyB0Q2hhbmNlIGFuZCBBTkNPVkFQb3N0IGJ5IEdlbmRlcg0KDQpgYGB7ciB0X0NoYW5nZV9BTkNPVkFfUG9zdHNfZ2VuLCBmaWcud2lkdGg9MTEsIGZpZy5oZWlnaHQ9MTIsIHJlc3VsdHM9J2FzaXMnfQ0KIyBGZW1hbGVzDQpjYXQoIiMjIyBGZW0iKQ0KRGF0YV9mZW0gJT4lDQogIGZ1bmNfYW5jb3ZhX211bHRpYm94KCJJRCIsICJPWFRfUHJlX09HTCIsICJPWFRfUG9zdF9PR0wiLCAiT1hUX1ByZV9FQ1JBTiIsICJPWFRfUG9zdF9FQ1JBTiIpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBucyAoUFJPQkxFTSkNCg0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YV9mZW0sICJJRCIsICJWYXNfU3RyZXNfUHJlX09HTCIsICJWYXNfU3RyZXNfUG9zdF9PR0wiLCAiVmFzX1N0cmVzX1ByZV9FQ1JBTiIsICJWYXNfU3RyZXNfUG9zdF9FQ1JBTiIpICAgICMgbnMNCg0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YV9mZW0sICJJRCIsICJWYXNfQmluZV9QcmVfT0dMIiwgIlZhc19CaW5lX1Bvc3RfT0dMIiwgIlZhc19CaW5lX1ByZV9FQ1JBTiIsICJWYXNfQmluZV9Qb3N0X0VDUkFOIikgICAgICAgICMgbnMNCg0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YV9mZW0sICJJRCIsICJJT1NfUHJlX09HTCIsICJJT1NfUG9zdF9PR0wiLCAiSU9TX1ByZV9FQ1JBTiIsICJJT1NfUG9zdF9FQ1JBTiIpICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgc2lnDQoNCiMgTWFsZXMNCmNhdCgiIyMjIE1hc2MiKQ0KRGF0YV9tYXNjICU+JQ0KICBmdW5jX2FuY292YV9tdWx0aWJveCgiSUQiLCAiT1hUX1ByZV9PR0wiLCAiT1hUX1Bvc3RfT0dMIiwgIk9YVF9QcmVfRUNSQU4iLCAiT1hUX1Bvc3RfRUNSQU4iKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG5zDQoNCmZ1bmNfYW5jb3ZhX211bHRpYm94KERhdGFfbWFzYywgIklEIiwgIlZhc19TdHJlc19QcmVfT0dMIiwgIlZhc19TdHJlc19Qb3N0X09HTCIsICJWYXNfU3RyZXNfUHJlX0VDUkFOIiwgIlZhc19TdHJlc19Qb3N0X0VDUkFOIikgICAgIyBucw0KDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhX21hc2MsICJJRCIsICJWYXNfQmluZV9QcmVfT0dMIiwgIlZhc19CaW5lX1Bvc3RfT0dMIiwgIlZhc19CaW5lX1ByZV9FQ1JBTiIsICJWYXNfQmluZV9Qb3N0X0VDUkFOIikgICAgICAgICMgbnMNCg0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YV9tYXNjLCAiSUQiLCAiSU9TX1ByZV9PR0wiLCAiSU9TX1Bvc3RfT0dMIiwgIklPU19QcmVfRUNSQU4iLCAiSU9TX1Bvc3RfRUNSQU4iKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHNpZw0KYGBgDQoNCg0KDQojIyBOb3QgY29uc2lkZXJpbmcgQ29uZCAoT2dsRWNyYW4pIC0gT3ZlcmFsbCBQcmUtUG9zdA0KDQpgYGB7ciB0X3Rlc3RfUHJlUG9zdCwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NywgcmVzdWx0cz0nYXNpcyd9DQojIERhdGENCnZhcnNfT2dsRWNyYW4gPC0gZ3JlcCgiT0dMfEVDUkFOIiwgY29sbmFtZXMoRGF0YV9tZXJnZWRfd2lkZV9hbGwpKQ0KDQpEYXRhX25vdE9nbEVjcmFuIDwtDQogIERhdGFfbWVyZ2VkX3dpZGVfYWxsICU+JQ0KICBnYXRoZXIodmFyaWFibGUsIHZhbHVlLCB2YXJzX09nbEVjcmFuLCAtYyhJRCkpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBnYXRoZXIgRGF0YSBhbmQgTnJfemkgYXMgdGhlc2UgYXJlIE9nbEVjcmFuIGxldmVsDQogIHRpZHlyOjpzZXBhcmF0ZSh2YXJpYWJsZSwgIGMoInZhcmlhYmxlIiwgIk9nbEVjcmFuIiksICJfKD89W15fXSskKSIpICU+JSAgICAgICAgICAgICAgICAjIHNwbGl0IG9ubHkgb24gbGFzdCAiXyINCiAgc3ByZWFkKHZhcmlhYmxlLCB2YWx1ZSkgJT4lIA0KICByZW5hbWVfYXQodmFycyh2YXJzX09nbEVjcmFuKSwgbGlzdCh+c3RyaW5ncjo6c3RyX3JlbW92ZV9hbGwoLiwgYygiX09HTHxfRUNSQU4iKSkpKSAlPiUgICANCiAgbXV0YXRlX2F0KHZhcnMoYyg0NTo0NiwgNDg6NTMpKSwgbGlzdCh+YXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoLikpKSkgJT4lDQogIG11dGF0ZShEaWZmX09YVCA9IE9YVF9Qb3N0IC0gT1hUX1ByZSwNCiAgICAgICAgIERpZmZfVmFzX1N0cmVzID0gVmFzX1N0cmVzX1Bvc3QgLSBWYXNfU3RyZXNfUHJlLA0KICAgICAgICAgRGlmZl9WYXNfQmluZSA9IFZhc19CaW5lX1Bvc3QgLSBWYXNfQmluZV9QcmUNCiAgKSAlPiUNCiAgYXJyYW5nZShJRCkNCiAgDQoNCiMgU2ltcGxlIGJlZm9yZS1hZnRlciBhbmFseXNlcyB3aXRoIHQgdGVzdCBOb3QgY29uc2lkZXJpbmcgQ29uZCAoT2dsRWNyYW4pDQpEYXRhX25vdE9nbEVjcmFuICU+JQ0KICBmaWx0ZXIoIUlEICVpbiUgYygxOSwgNDMpKSAlPiUNCiAgZnVuY190X2JveCgiSUQiLCAiT1hUX1ByZSIsICJPWFRfUG9zdCIpICAgICMgSlVTVCBTSFkgT0YgU0lHDQoNCmZ1bmNfdF9ib3goRGF0YV9ub3RPZ2xFY3JhbiwgIklEIiwgIlZhc19TdHJlc19QcmUiLCAiVmFzX1N0cmVzX1Bvc3QiKSAgICAgICAgICMgc2lnICANCg0KZnVuY190X2JveChEYXRhX25vdE9nbEVjcmFuLCAiSUQiLCAiVmFzX0JpbmVfUHJlIiwgIlZhc19CaW5lX1Bvc3QiKSAgICAgICAgICAgIyBzaWcgIA0KDQpmdW5jX3RfYm94KERhdGFfbm90T2dsRWNyYW4sICJJRCIsICJJT1NfUHJlIiwgIklPU19Qb3N0IikgICAgICAgICAgICAgICAgICAgICAjIHNpZyAgDQoNCg0KDQojIEdHcGFpcnMNCmZuX2dncGFpcl9yZWcgPC0gZnVuY3Rpb24oZGF0YSwgbWFwcGluZywgLi4uKXsNCiAgcCA8LSBnZ3Bsb3QoZGF0YSA9IGRhdGEsIG1hcHBpbmcgPSBtYXBwaW5nKSArIA0KICAgIGdlb21fcG9pbnQoKSArIA0KICAgIGdlb21fc21vb3RoKG1ldGhvZD1sb2VzcywgZmlsbD0icmVkIiwgY29sb3I9InJlZCIsIC4uLikgKw0KICAgIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgZmlsbD0iYmx1ZSIsIGNvbG9yPSJibHVlIiwgLi4uKQ0KICBwDQp9DQoNCkdHYWxseTo6Z2dwYWlycyhkYXRhID0gRGF0YV9ub3RPZ2xFY3JhbiAlPiUgZmlsdGVyKCFJRCAlaW4lIGMoMTksIDQzKSksDQogICAgICAgICAgICAgICAgY29sdW1ucyA9IDU0OjU2LCANCiAgICAgICAgICAgICAgICBsb3dlciA9IGxpc3QoY29udGludW91cyA9IGZuX2dncGFpcl9yZWcpKQ0KYGBgDQoNCg0KIyMgRGlmZmVyZW5jZSBzY29yZXMgY29uZGl0aW9uZWQgb24gQW54aWV0eSA/DQoNCmBgYHtyIHBsb3RfY29yX2FueCwgcmVzdWx0cz0nYXNpcycsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xNCwgZmlnLmFsaWduPSdjZW50ZXInfQ0KcGxvdF9jb2x1bW5zIDwtIG1hdGNoKCBjKCJTdGFpU2JydXQiLCAiU3RhaVRicnV0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAiRGlmZl9PWFRfT0dMIiwgIkRpZmZfT1hUX0VDUkFOIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAiRGlmZl9WYXNfU3RyZXNfT0dMIiwgIkRpZmZfVmFzX1N0cmVzX0VDUkFOIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAiRGlmZl9WYXNfQmluZV9PR0wiLCAiRGlmZl9WYXNfQmluZV9FQ1JBTiIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXMoRGF0YV9kaWZzY29yZXMpKQ0KDQojIEdHcGFpcnMNCmZuX2dncGFpcl9yZWcgPC0gZnVuY3Rpb24oZGF0YSwgbWFwcGluZywgLi4uKXsNCiAgcCA8LSBnZ3Bsb3QoZGF0YSA9IGRhdGEsIG1hcHBpbmcgPSBtYXBwaW5nKSArIA0KICAgIGdlb21fcG9pbnQoKSArIA0KICAgIGdlb21fc21vb3RoKG1ldGhvZD1sb2VzcywgZmlsbD0icmVkIiwgY29sb3I9InJlZCIsIC4uLikgKw0KICAgIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgZmlsbD0iYmx1ZSIsIGNvbG9yPSJibHVlIiwgLi4uKQ0KICBwDQp9DQoNCkdHYWxseTo6Z2dwYWlycyhkYXRhID0gRGF0YV9kaWZzY29yZXMsDQogICAgICAgICAgICAgICAgY29sdW1ucyA9IHBsb3RfY29sdW1ucywgDQogICAgICAgICAgICAgICAgbG93ZXIgPSBsaXN0KGNvbnRpbnVvdXMgPSBmbl9nZ3BhaXJfcmVnKSkNCg0KIyBHR3BhaXJzIEJ5IEdlbg0KR0dhbGx5OjpnZ3BhaXJzKGRhdGEgPSBEYXRhX2RpZnNjb3JlcywNCiAgICAgICAgICAgICAgICBjb2x1bW5zID0gcGxvdF9jb2x1bW5zLCANCiAgICAgICAgICAgICAgICB0aXRsZSA9ICJjb3JyZWxhdGlvbiBtYXRyaXgiLCAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIG1hcHBpbmcgPSBhZXMoY29sb3VyID0gR2VuKSwgDQogICAgICAgICAgICAgICAgbG93ZXIgPSBsaXN0KA0KICAgICAgICAgICAgICAgIGNvbnRpbnVvdXMgPSAic21vb3RoIiwNCiAgICAgICAgICAgICAgICBjb21ibyA9ICJmYWNldGRlbnNpdHkiLA0KICAgICAgICAgICAgICAgIG1hcHBpbmcgPSBhZXMoY29sb3IgPSBHZW4pKSwNCiAgICAgICAgICAgICAgICB1cHBlciA9IGxpc3QoY29udGludW91cyA9IHdyYXAoImNvciIsIHNpemUgPSAzLCBoanVzdD0wLjgpKSkNCmBgYA0KDQpgYGB7ciBwbG90X2NvbmRfYW54LCByZXN1bHRzPSdhc2lzJywgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OCwgZmlnLmFsaWduPSdjZW50ZXInfQ0KIyBDb3Bsb3QgQW54IA0KRGF0YV9kaWZzY29yZXMgJT4lDQogIGZpbHRlcighSUQgJWluJSBjKDE5LCA0MykpICU+JQ0KICAgIGNvcGxvdChEaWZmX09YVF9PR0wgfiBEaWZmX1Zhc19TdHJlc19PR0wgfCBTdGFpVGJydXQsDQogICAgICAgICAgIGRhdGEgPSAuLA0KICAgICAgICAgICByb3dzID0gMSwNCiAgICAgICAgICAgcGFuZWwgPSBmdW5jdGlvbih4LCB5LCAuLi4pIHsNCiAgICAgICAgICAgcGFuZWwuc21vb3RoKHgsIHksIHNwYW4gPSAuOCwgaXRlciA9IDUsLi4uKQ0KICAgICAgICAgICBhYmxpbmUobG0oeSB+IHgpLCBjb2wgPSAiYmx1ZSIpfSkNCg0KRGF0YV9kaWZzY29yZXMgJT4lDQogIGZpbHRlcighSUQgJWluJSBjKDE5LCA0MykpICU+JQ0KICAgIGNvcGxvdChEaWZmX09YVF9FQ1JBTiB+IERpZmZfVmFzX1N0cmVzX0VDUkFOIHwgU3RhaVRicnV0LA0KICAgICAgICAgICBkYXRhID0gLiwNCiAgICAgICAgICAgcm93cyA9IDEsDQogICAgICAgICAgIHBhbmVsID0gZnVuY3Rpb24oeCwgeSwgLi4uKSB7DQogICAgICAgICAgIHBhbmVsLnNtb290aCh4LCB5LCBzcGFuID0gLjgsIGl0ZXIgPSA1LC4uLikNCiAgICAgICAgICAgYWJsaW5lKGxtKHkgfiB4KSwgY29sID0gImJsdWUiKX0pDQoNCg0KRGF0YV9kaWZzY29yZXMgJT4lDQogIGZpbHRlcighSUQgJWluJSBjKDE5LCA0MykpICU+JQ0KICBjb3Bsb3QoRGlmZl9PWFRfT0dMIH4gRGlmZl9WYXNfU3RyZXNfT0dMIHwgU3RhaVNicnV0LA0KICAgICAgICAgZGF0YSA9IC4sDQogICAgICAgICByb3dzID0gMSwNCiAgICAgICAgIHBhbmVsID0gZnVuY3Rpb24oeCwgeSwgLi4uKSB7DQogICAgICAgICAgIHBhbmVsLnNtb290aCh4LCB5LCBzcGFuID0gLjgsIGl0ZXIgPSA1LC4uLikNCiAgICAgICAgICAgYWJsaW5lKGxtKHkgfiB4KSwgY29sID0gImJsdWUiKX0pDQoNCkRhdGFfZGlmc2NvcmVzICU+JQ0KICBmaWx0ZXIoIUlEICVpbiUgYygxOSwgNDMpKSAlPiUNCiAgY29wbG90KERpZmZfT1hUX0VDUkFOIH4gRGlmZl9WYXNfU3RyZXNfRUNSQU4gfCBTdGFpU2JydXQsDQogICAgICAgICBkYXRhID0gLiwNCiAgICAgICAgIHJvd3MgPSAxLA0KICAgICAgICAgcGFuZWwgPSBmdW5jdGlvbih4LCB5LCAuLi4pIHsNCiAgICAgICAgICAgcGFuZWwuc21vb3RoKHgsIHksIHNwYW4gPSAuOCwgaXRlciA9IDUsLi4uKQ0KICAgICAgICAgICBhYmxpbmUobG0oeSB+IHgpLCBjb2wgPSAiYmx1ZSIpfSkNCmBgYA0KDQoNCiMjIERpZmZlcmVuY2Ugc2NvcmVzIGNvbmRpdGlvbmVkIG9uIEV4dHJhdmVyc2lvbiA/DQoNCmBgYHtyIHBsb3RfY29yX2UsIHJlc3VsdHM9J2FzaXMnLCBmaWcuaGVpZ2h0PTE0LCBmaWcud2lkdGg9MTQsIGZpZy5hbGlnbj0nY2VudGVyJ30NCnBsb3RfY29sdW1ucyA8LSBtYXRjaChjKCJFIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJEaWZmX09YVF9PR0wiLCAiRGlmZl9PWFRfRUNSQU4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgIkRpZmZfVmFzX1N0cmVzX09HTCIsICJEaWZmX1Zhc19TdHJlc19FQ1JBTiIsDQogICAgICAgICAgICAgICAgICAgICAgICAiRGlmZl9WYXNfQmluZV9PR0wiLCAiRGlmZl9WYXNfQmluZV9FQ1JBTiIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzKERhdGFfZGlmc2NvcmVzKSkNCg0KIyBHR3BhaXJzDQpmbl9nZ3BhaXJfcmVnIDwtIGZ1bmN0aW9uKGRhdGEsIG1hcHBpbmcsIC4uLil7DQogIHAgPC0gZ2dwbG90KGRhdGEgPSBkYXRhLCBtYXBwaW5nID0gbWFwcGluZykgKyANCiAgICBnZW9tX3BvaW50KCkgKyANCiAgICBnZW9tX3Ntb290aChtZXRob2Q9bG9lc3MsIGZpbGw9InJlZCIsIGNvbG9yPSJyZWQiLCAuLi4pICsNCiAgICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIGZpbGw9ImJsdWUiLCBjb2xvcj0iYmx1ZSIsIC4uLikNCiAgcA0KfQ0KDQpHR2FsbHk6OmdncGFpcnMoZGF0YSA9IERhdGFfZGlmc2NvcmVzLA0KICAgICAgICAgICAgICAgIGNvbHVtbnMgPSBwbG90X2NvbHVtbnMsIA0KICAgICAgICAgICAgICAgIGxvd2VyID0gbGlzdChjb250aW51b3VzID0gZm5fZ2dwYWlyX3JlZykpDQpgYGANCg0KDQoNCjwhLS0NCg0KIyMgTW9kZXJhdGlvbiBBbmFseXNpcyAoKQ0KDQpgYGB7ciBzaW1wbGVfbW9kX2UsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTYsIHJlc3VsdHM9J2FzaXMnLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KIyMgRGVmaW5lIEZ1bmN0aW9uDQpmdW5jX21vZGVyYXRpb24gPC0gZnVuY3Rpb24oRGF0YSwgZGVwLCBtb2QsIHByZWQpew0KICBtb2RlcmF0aW9uIDwtIA0KICAgIERhdGEgJT4lDQogICAgbWVkbW9kOjptb2QoLiwgZGVwID0gZGVwLCBtb2QgPSBtb2QsIHByZWQgPSBwcmVkLA0KICAgICAgICAgICAgICAgIGNpID0gVFJVRSwgZXN0TWV0aG9kID0gJ3N0YW5kYXJkJywgdGVzdCA9IFRSVUUsIHNpbXBsZVNsb3BlRXN0ID0gRkFMU0UsIHNpbXBsZVNsb3BlUGxvdCA9IFRSVUUpDQogIA0KICBjYXQocGFzdGUoIjxiPiBNb2RlcmF0aW9uOiAiLCAiRGVwID0gIiwgZGVwLCAiUHJlZCA9ICIsIHByZWQsICJNb2QgPSAiLCBtb2QsICI8L2I+IikpDQogIG1vZGVyYXRpb24kbW9kICU+JSANCiAgICBrbml0cjo6a2FibGUoY2FwdGlvbiA9ICJNb2RlcmF0aW9uIiwgZGlnaXRzID0gMykgJT4lDQogICAgcHJpbnQoKQ0KICBtb2RlcmF0aW9uJHNpbXBsZVNsb3BlJHBsb3QgJT4lDQogICAgcHJpbnQoKQ0KfQ0KDQoNCkRhdGFfbWVyZ2VkX3dpZGVfYWxsICU+JQ0KICBmaWx0ZXIoIUlEICVpbiUgYygxOSwgNDMpKSAlPiUNCiAgZnVuY19tb2RlcmF0aW9uKERhdGEgPSAuLCBkZXAgPSAiT1hUX1Bvc3RfT0dMIiwgbW9kID0gIkUiLCBwcmVkID0gIk9YVF9QcmVfT0dMIikNCg0KRGF0YV9tZXJnZWRfd2lkZV9hbGwgJT4lDQogIGZpbHRlcighSUQgJWluJSBjKDE5LCA0MykpICU+JQ0KICBmdW5jX21vZGVyYXRpb24oRGF0YSA9IC4sIGRlcCA9ICJPWFRfUG9zdF9FQ1JBTiIsIG1vZCA9ICJFIiwgcHJlZCA9ICJPWFRfUHJlX0VDUkFOIikNCg0KDQpjYXQoIiMjIyBBTkNPVkEgLSBFeHRyYXZlcnNpb24iKQ0KZGZfYW5jb3ZhX2UgPC0NCiAgRGF0YV9tZXJnZWRfd2lkZV9hbGwgJT4lDQogIHNlbGVjdCgiSUQiLCAiT1hUX1ByZV9PR0wiLCAiT1hUX1Bvc3RfT0dMIiwgIk9YVF9QcmVfRUNSQU4iLCAiT1hUX1Bvc3RfRUNSQU4iLCAiRSIpICU+JQ0KICB0aWR5cjo6ZHJvcF9uYSgpICU+JQ0KICBnYXRoZXIoIk9YVF9QcmVfT0dMIiwgIk9YVF9Qb3N0X09HTCIsICJPWFRfUHJlX0VDUkFOIiwgIk9YVF9Qb3N0X0VDUkFOIiwga2V5ID0gIkNvbmQiLCB2YWx1ZSA9ICJ2YWx1ZSIpICU+JQ0KICBtdXRhdGUoUHJlUG9zdCA9IGNhc2Vfd2hlbihzdHJpbmdyOjpzdHJfZGV0ZWN0KC4kIkNvbmQiLCAiUHJlIikgfiAiUHJlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5ncjo6c3RyX2RldGVjdCguJCJDb25kIiwgIlBvc3QiKSB+ICJQb3N0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgT2dsRWNyYW4gPSBjYXNlX3doZW4oc3RyaW5ncjo6c3RyX2RldGVjdCguJCJDb25kIiwgIk9HTCIpIH4gIk9HTCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KC4kIkNvbmQiLCAiRUNSQU4iKSB+ICJFQ1JBTiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXykpICU+JQ0KICBtdXRhdGUoUHJlUG9zdCA9IGFzLmZhY3RvcihQcmVQb3N0KSwNCiAgICAgICAgIE9nbEVjcmFuID0gYXMuZmFjdG9yKE9nbEVjcmFuKSkgJT4lDQogIHNlbGVjdCgtIkNvbmQiKSAlPiUNCiAgc3ByZWFkKCJQcmVQb3N0IiwgInZhbHVlIikNCg0KDQpqbXY6OmFuY292YSgNCiAgICBmb3JtdWxhID0gUG9zdCB+IFByZSArIE9nbEVjcmFuICsgRSwNCiAgICBkYXRhID0gZGZfYW5jb3ZhX2UsDQogICAgaG9tbyA9IFRSVUUsDQogICAgc3MgPSAiMyIsDQogICAgcG9zdEhvYyA9IH4gT2dsRWNyYW4sDQogICAgcG9zdEhvY0NvcnIgPSBsaXN0KCJ0dWtleSIpLA0KICAgIGVmZmVjdFNpemUgPSBsaXN0KCJldGEiLCAicGFydEV0YSIpDQogICkNCmBgYA0KDQoNCg0KDQpgYGB7ciBzaW1wbGVfbW9kX2FueCwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9NiwgcmVzdWx0cz0nYXNpcycsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQojIyBEZWZpbmUgRnVuY3Rpb24NCmZ1bmNfbW9kZXJhdGlvbiA8LSBmdW5jdGlvbihEYXRhLCBkZXAsIG1vZCwgcHJlZCl7DQogIG1vZGVyYXRpb24gPC0gDQogICAgRGF0YSAlPiUNCiAgICAgIG1lZG1vZDo6bW9kKC4sIGRlcCA9IGRlcCwgbW9kID0gbW9kLCBwcmVkID0gcHJlZCwNCiAgICAgICAgICAgICAgICAgIGNpID0gVFJVRSwgZXN0TWV0aG9kID0gJ3N0YW5kYXJkJywgdGVzdCA9IFRSVUUsIHNpbXBsZVNsb3BlRXN0ID0gRkFMU0UsIHNpbXBsZVNsb3BlUGxvdCA9IFRSVUUpDQogIA0KICBjYXQocGFzdGUoIjxiPiBNb2RlcmF0aW9uOiAiLCAiRGVwID0gIiwgZGVwLCAiUHJlZCA9ICIsIHByZWQsICJNb2QgPSAiLCBtb2QsICI8L2I+IikpDQogIG1vZGVyYXRpb24kbW9kICU+JSANCiAgICBrbml0cjo6a2FibGUoY2FwdGlvbiA9ICJNb2RlcmF0aW9uIiwgZGlnaXRzID0gMykgJT4lDQogICAgcHJpbnQoKQ0KICBtb2RlcmF0aW9uJHNpbXBsZVNsb3BlJHBsb3QgJT4lDQogICAgcHJpbnQoKQ0KfQ0KDQojIyBBcHBseSBGdW5jdGlvbg0KRGF0YV9tZXJnZWRfd2lkZV9hbGwgJT4lDQogIGZpbHRlcighSUQgJWluJSBjKDE5LCA0MykpICU+JQ0KICBmdW5jX21vZGVyYXRpb24oRGF0YSA9IC4sIGRlcCA9ICJPWFRfUG9zdF9PR0wiLCBtb2QgPSAiU3RhaVRicnV0IiwgcHJlZCA9ICJPWFRfUHJlX09HTCIpDQoNCkRhdGFfbWVyZ2VkX3dpZGVfYWxsICU+JQ0KICBmaWx0ZXIoIUlEICVpbiUgYygxOSwgNDMpKSAlPiUNCiAgZnVuY19tb2RlcmF0aW9uKERhdGEgPSAuLCBkZXAgPSAiT1hUX1Bvc3RfRUNSQU4iLCBtb2QgPSAiU3RhaVRicnV0IiwgcHJlZCA9ICJPWFRfUHJlX0VDUkFOIikNCg0KDQoNCg0KDQojIGJsYSA8LQ0KIyAgIERhdGFfbWVyZ2VkICU+JQ0KIyAgIG11dGF0ZShDb25kaXRpZSA9IGFzLm51bWVyaWMoYXMuZmFjdG9yKENvbmRpdGllKSkpDQojIA0KIyBwc3ljaDo6bWVkaWF0ZShkYXRhID0gYmxhLCBPeGl0b2NpbmFfcG9zdCB+IE94aXRvY2luYV9wcmUgKyBDb25kaXRpZSArIFZhc19yZWxfZ2xvYmFsKSAgICMgbW9kZXJhdGlvbiB3aXRoIGNvdmFyaWF0ZSBhbmQgZGlhZ3JhbQ0KYGBgDQoNCg0KDQoNCg0KIyMgTWl4ZWQgRGVzaWduIEFOT1ZBDQoNCmBgYHtyIG1peGVkX2Fub3ZhLCBmaWcud2lkdGg9MTEsIGZpZy5oZWlnaHQ9MTIsIHJlc3VsdHM9J2FzaXMnfQ0KIyBEYXRhDQpEYXRhX21peGVkYW5vdmEgPC0NCiAgRGF0YV9tZXJnZWRfbG9uZ19hbGwgJT4lDQogIG11dGF0ZShQcmVQb3N0ID0gY2FzZV93aGVuKHN0cmluZ3I6OnN0cl9kZXRlY3QoLiQiUHJlUG9zdCIsICJQcmUiKSB+IGFzLmludGVnZXIoMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3I6OnN0cl9kZXRlY3QoLiQiUHJlUG9zdCIsICJQb3N0IikgfiBhcy5pbnRlZ2VyKDEpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gTkFfaW50ZWdlcl8pKSAlPiUNCiAgbXV0YXRlKE9nbEVjcmFuID0gY2FzZV93aGVuKHN0cmluZ3I6OnN0cl9kZXRlY3QoLiQiT2dsRWNyYW4iLCAiRUNSQU4iKSB+IGFzLmludGVnZXIoMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KC4kIk9nbEVjcmFuIiwgIk9HTCIpIH4gYXMuaW50ZWdlcigxKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBOQV9pbnRlZ2VyXykpICU+JQ0KICBtdXRhdGUoU3RhaVRicnV0X2RpaCA9IHNqbWlzYzo6ZGljaG8oLiQiU3RhaVRicnV0IiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWNoLmJ5ID0gIm1lZGlhbiIsIGFzLm51bSA9IEZBTFNFLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzaW1pbGFyIHRvIEhtaXNjOjpjdXQyLCBidXQgdXNlcyBtZWRpYW4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbC5sYWJlbHMgPSBjKCJsb3dlciIsICJoaWdoZXIiKSwgYXBwZW5kID0gRkFMU0UpKSAlPiUNCiAgc2VsZWN0KElELCBPZ2xFY3JhbiwgUHJlUG9zdCwgT1hULCBTdGFpVGJydXRfZGloKSAlPiUNCiAgZHJvcF9uYSgpDQogICAgICAgICAgIA0KICAgIA0KIyBNaXhlZCBEZXNpZ24gQW5vdmEgICMgaHR0cDovL3d3dy5jb29rYm9vay1yLmNvbS9TdGF0aXN0aWNhbF9hbmFseXNpcy9BTk9WQS8NCmFvdl9taXhlZDEgPC0gYW92KE9YVCB+IE9nbEVjcmFuICogUHJlUG9zdCAqIFN0YWlUYnJ1dF9kaWggKyBFcnJvcihJRC9QcmVQb3N0KSwgZGF0YSA9IERhdGFfbWl4ZWRhbm92YSkgDQpicm9vbTo6dGlkeShhb3ZfbWl4ZWQxKQ0KIyBzdW1tYXJ5KGFvdl9taXhlZDEpICAgDQojIG1vZGVsLnRhYmxlcyhhb3ZfbWl4ZWQxLCAibWVhbnMiKSAgICMgaXMgZGF0YSBiYWxhbmNlZD8NCg0KDQoNCg0KIyBsaWJyYXJ5KGp0b29scykNCiMgbW9kMSA8LSBsbShPWFRfUG9zdF9PR0wgfiBPWFRfUHJlX09HTCAqIFN0YWlUYnJ1dCwgZGF0YSA9IERhdGFfbWl4ZWRhbm92YSkNCiMganRvb2xzOjpzdW1tKG1vZDEpDQojIGp0b29sczo6aW50ZXJhY3RfcGxvdChtb2QxLCBwcmVkID0gT1hUX1ByZV9PRywgbW9keCA9IFN0YWlUYnJ1dCkNCiMgDQojIGxpYnJhcnkoaW50ZXJhY3Rpb25zKQ0KYGBgDQoNCg0KLS0+DQoNCiMjIENvcnJlbGF0aW9ucyBiZXR3ZWVuIERpZmZfT1hUX09HTCB3aXRoIG90aGVyIHZhcmlhYmxlcw0KDQpgYGB7ciBEX2Nvcl9vdGhlciwgcmVzdWx0cz0nYXNpcycsIHdhcm5pbmc9RkFMU0V9DQojIyBDb3JyZWxhdGlvbnMgYmV0d2VlbiBEaWZmcmVuY2UgU2NvcmVzIHdpdGggb3RoZXIgdmFyaWFibGVzDQpEYXRhX2RpZnNjb3Jlc1ssLWMoMToyLCA1OjI0KV0gJT4lDQogIENvcnJlbGF0aW9uc19XaXRoX09uZSguLCB2YXJpYWJsZSA9ICJEaWZmX09YVF9PR0wiLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICAjIG5vdGhpbmcNCg0KDQojIyMjDQpEYXRhX2RpZnNjb3Jlc1ssLWMoMToyLCA1OjI0KV0gJT4lDQogICBDb3JyZWxhdGlvbnNfV2l0aF9PbmUoLiwgdmFyaWFibGUgPSAiRGlmZl9WYXNfU3RyZXNfT0dMIiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICMgQyxDNQ0KDQojIyMNCkRhdGFfZGlmc2NvcmVzWywtYygxOjIsIDU6MjQpXSAlPiUNCiAgIENvcnJlbGF0aW9uc19XaXRoX09uZSguLCB2YXJpYWJsZSA9ICJEaWZmX1Zhc19CaW5lX09HTCIsIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjA1KSAgIyBCREkNCkRhdGFfZGlmc2NvcmVzWywtYygxOjIsIDU6MjQpXSAlPiUNCiAgIENvcnJlbGF0aW9uc19XaXRoX09uZSguLCB2YXJpYWJsZSA9ICJEaWZmX1Zhc19CaW5lX0VDUkFOIiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICMgTzIsTzMsIFN0YWlUDQoNCmBgYA0KDQoNCmBgYHtyIGxtX3ZhciwgcmVzdWx0cz0nYXNpcycsIHdhcm5pbmc9RkFMU0V9DQpsbShWYXNfU3RyZXNfUG9zdF9PR0wgfiBWYXNfU3RyZXNfUHJlX09HTCArIFN0YWlUYnJ1dCwgZGF0YSA9IERhdGFfbWVyZ2VkX3dpZGVfYWxsKSAlPiUgc3VtbWFyeSgpICAgICAgIyBzaWcNCmxtKFZhc19TdHJlc19Qb3N0X0VDUkFOIH4gVmFzX1N0cmVzX1ByZV9FQ1JBTiArIFN0YWlUYnJ1dCwgZGF0YSA9IERhdGFfbWVyZ2VkX3dpZGVfYWxsKSAlPiUgc3VtbWFyeSgpICAjIG5zDQoNCg0KbG0oVmFzX0JpbmVfUG9zdF9PR0wgfiBWYXNfQmluZV9QcmVfT0dMICsgU2NvckJESSwgZGF0YSA9IERhdGFfbWVyZ2VkX3dpZGVfYWxsKSAlPiUgc3VtbWFyeSgpICAgICAgICAjIHNpZw0KbG0oVmFzX0JpbmVfUG9zdF9FQ1JBTiB+IFZhc19CaW5lX1ByZV9FQ1JBTiArIFNjb3JCREksIGRhdGEgPSBEYXRhX21lcmdlZF93aWRlX2FsbCkgJT4lIHN1bW1hcnkoKSAgICAjIG5zDQoNCg0KDQoNCmBgYA0KDQoNCiMjIENvcnJlbGF0aW9ucyBiZXR3ZWVuIERpZmZfT1hUX09HTCB3aXRoIG90aGVyIHZhcmlhYmxlcyAtIGJ5IEdlbmRlcg0KDQpgYGB7ciBEX2Nvcl9vdGhlcl9nZW4sIHJlc3VsdHM9J2FzaXMnLCB3YXJuaW5nPUZBTFNFfQ0KIyMgQ29ycmVsYXRpb25zIGJldHdlZW4gRGlmZnJlbmNlIFNjb3JlcyB3aXRoIG90aGVyIHZhcmlhYmxlcyAtIEZlbWFsZXMNCmNhdCgiIyMjIEZlbWFsZXMiKQ0KRGF0YV9kaWZzY29yZXNbLC1jKDE6MiwgNToyNCldICU+JQ0KICBmaWx0ZXIoR2VuID09ICJmIikgJT4lDQogIENvcnJlbGF0aW9uc19XaXRoX09uZSguLCB2YXJpYWJsZSA9ICJEaWZmX09YVF9PR0wiLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICAjIG5vdGhpbmcNCg0KIyMjIw0KRGF0YV9kaWZzY29yZXNbLC1jKDE6MiwgNToyNCldJT4lDQogIGZpbHRlcihHZW4gPT0gImYiKSAlPiUNCiAgIENvcnJlbGF0aW9uc19XaXRoX09uZSguLCB2YXJpYWJsZSA9ICJEaWZmX1Zhc19TdHJlc19PR0wiLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgIyBBMQ0KDQojIyMNCkRhdGFfZGlmc2NvcmVzWywtYygxOjIsIDU6MjQpXSAlPiUNCiAgZmlsdGVyKEdlbiA9PSAiZiIpICU+JQ0KICBDb3JyZWxhdGlvbnNfV2l0aF9PbmUoLiwgdmFyaWFibGUgPSAiRGlmZl9WYXNfQmluZV9PR0wiLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgQkRJLCBOMg0KRGF0YV9kaWZzY29yZXNbLC1jKDE6MiwgNToyNCldICU+JQ0KICBmaWx0ZXIoR2VuID09ICJmIikgJT4lDQogIENvcnJlbGF0aW9uc19XaXRoX09uZSguLCB2YXJpYWJsZSA9ICJEaWZmX1Zhc19CaW5lX0VDUkFOIiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICMgU3RhaVQNCg0KDQoNCg0KIyMgQ29ycmVsYXRpb25zIGJldHdlZW4gRGlmZnJlbmNlIFNjb3JlcyB3aXRoIG90aGVyIHZhcmlhYmxlcyAtIE1hbGVzDQpjYXQoIiMjIyBNYWxlcyIpDQpEYXRhX2RpZnNjb3Jlc1ssLWMoMToyLCA1OjI0KV0gJT4lDQogIGZpbHRlcihHZW4gPT0gIm0iKSAlPiUNCiAgQ29ycmVsYXRpb25zX1dpdGhfT25lKC4sIHZhcmlhYmxlID0gIkRpZmZfT1hUX09HTCIsIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjA1KSAgICMgTzYsQTYNCg0KIyMjIw0KRGF0YV9kaWZzY29yZXNbLC1jKDE6MiwgNToyNCldICU+JQ0KICBmaWx0ZXIoR2VuID09ICJtIikgJT4lDQogIENvcnJlbGF0aW9uc19XaXRoX09uZSguLCB2YXJpYWJsZSA9ICJEaWZmX1Zhc19TdHJlc19PR0wiLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgIyBDMi1PcmRpbmUhISENCg0KIyMjDQpEYXRhX2RpZnNjb3Jlc1ssLWMoMToyLCA1OjI0KV0gJT4lDQogIGZpbHRlcihHZW4gPT0gIm0iKSAlPiUNCiAgQ29ycmVsYXRpb25zX1dpdGhfT25lKC4sIHZhcmlhYmxlID0gIkRpZmZfVmFzX0JpbmVfT0dMIiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICAjIG5vdGhpbmcNCkRhdGFfZGlmc2NvcmVzWywtYygxOjIsIDU6MjQpXSAlPiUNCiAgZmlsdGVyKEdlbiA9PSAibSIpICU+JQ0KICBDb3JyZWxhdGlvbnNfV2l0aF9PbmUoLiwgdmFyaWFibGUgPSAiRGlmZl9WYXNfQmluZV9FQ1JBTiIsIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjA1KSAjIEMyLU9yZGluZSxPMg0KDQpgYGANCg0KDQoNCiMgd2l0aGluLXBhcnRpY2lwYW50IG1lZGlhdGlvbg0KDQpgYGB7ciB3bWVkLCByZXN1bHRzPSdhc2lzJ30NCmxpYnJhcnkoSlNtZWRpYXRpb24pDQoNCmRmX2NvcmRpZl9mZW0gPC0gDQogIERhdGFfZGlmc2NvcmVzICU+JQ0KICBmaWx0ZXIoR2VuID09ICJmIikNCg0KY29yLnRlc3QoZGZfY29yZGlmX2ZlbSREaWZmX09YVF9PR0wsIGRmX2NvcmRpZl9mZW0kRGlmZl9WYXNfU3RyZXNfT0dMKSAgIyBucw0KDQpzdW1tYXJ5KGxtKERpZmZfT1hUX09HTCB+IERpZmZfVmFzX1N0cmVzX09HTCwgZGF0YSA9IGRmX2NvcmRpZl9mZW0pKSAgICMgbnMNCg0Kd2l0aGlubWVkX09HTCA8LSANCiAgbWR0X3dpdGhpbl93aWRlKGRhdGEgPSBEYXRhX2ZlbSwgDQogICAgICAgICAgICAgICAgICBEVl9BID0gVmFzX1N0cmVzX1ByZV9PR0wsIERWX0IgPSBWYXNfU3RyZXNfUG9zdF9PR0wsIA0KICAgICAgICAgICAgICAgICAgTV9BID0gT1hUX1ByZV9PR0wsIE1fQiA9IE9YVF9Qb3N0X09HTCkNCmFkZF9pbmRleCh3aXRoaW5tZWRfT0dMKQ0KDQp3aXRoaW5tZWRfRUNSQU4gPC0gDQogIG1kdF93aXRoaW5fd2lkZShkYXRhID0gRGF0YV9mZW0sIA0KICAgICAgICAgICAgICAgICAgRFZfQSA9IFZhc19TdHJlc19QcmVfRUNSQU4sIERWX0IgPSBWYXNfU3RyZXNfUG9zdF9FQ1JBTiwgDQogICAgICAgICAgICAgICAgICBNX0EgPSBPWFRfUHJlX0VDUkFOLCBNX0IgPSBPWFRfUG9zdF9FQ1JBTikNCmFkZF9pbmRleCh3aXRoaW5tZWRfRUNSQU4pDQoNCg0KDQoNCiMgbWR0X3dpdGhpbl93aWRlKGRhdGEgPSBEYXRhX2ZlbSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG5zDQojICAgICAgICAgICAgICAgICBEVl9BID0gVmFzX0JpbmVfUHJlX09HTCwgRFZfQiA9IFZhc19CaW5lX1Bvc3RfT0dMLA0KIyAgICAgICAgICAgICAgICAgTV9BID0gT1hUX1ByZV9PR0wsIE1fQiA9IE9YVF9Qb3N0X09HTCkNCg0KIyBtZHRfd2l0aGluX3dpZGUoZGF0YSA9IERhdGFfZmVtLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbnMNCiMgICAgICAgICAgICAgICAgIERWX0EgPSBJT1NfUHJlX09HTCwgRFZfQiA9IElPU19Qb3N0X09HTCwNCiMgICAgICAgICAgICAgICAgIE1fQSA9IE9YVF9QcmVfT0dMLCBNX0IgPSBPWFRfUG9zdF9PR0wpDQpgYGANCg0KDQoNCg0KDQoNCiMjIENvcnJlbGF0aW9ucyB3aXRoIE94VA0KDQpgYGB7ciBjb3JfT1hULCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD03LCByZXN1bHRzPSdhc2lzJ30NCiMjIE1pbmluZyBDb3JyZWxhdGlvbnMgd2l0aCBPeHkNCg0KIyBkZl9PeHlBbGxfY29yIDwtDQojICAgR2V0X1RvcF9SZWxhdGlvbnNoaXBzKERhdGFbLC1jKDE6NyldLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgJT4lDQojICAgICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lDQojICAgICBkcGx5cjo6ZmlsdGVyX2FsbChhbnlfdmFycyhncmVwbCgiT3giLCAuKSkpICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBvbmx5IE94eSwgYnV0IGJvdGggUHJlIGFuZCBQb3N0IE94eQ0KIyANCiMgZGZfT3h5QWxsX2NvciAlPiUgICAgICAgICAgICAgIA0KIyAgICAgcHJpbnQobiA9IEluZikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQojIGRmX094eUFsbF9jb3IgJT4lDQojICAgZnVuY19kb3RwbG90X2NvcigpDQojICANCiMgIyBDb3JyZWxhdGlvbnMgb25seSBvbiBQcmUgbWVhc3VyZXMgd2l0aCBPeHkgLS0gbm90aGluZw0KIyBkZl9PeHlQcmVfY29yIDwtIA0KIyAgIEdldF9Ub3BfUmVsYXRpb25zaGlwcyhEYXRhWywtYygxOjcpXSwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMSkgJT4lDQojICAgICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lDQojICAgICBmaWx0ZXJfYXQodmFycyhmZWF0dXJlXzEsIGZlYXR1cmVfMiksIGFsbF92YXJzKGdyZXBsKCJwcmV8UHJlIiwgLikpKSAlPiUNCiMgICAgIGRwbHlyOjpmaWx0ZXJfYWxsKGFueV92YXJzKGdyZXBsKCJPeCIsIC4pKSkgDQpgYGANCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo8YnI+DQoNCg0KDQo8IS0tIFNlc3Npb24gSW5mbyBhbmQgTGljZW5zZSAtLT4NCg0KPGJyPg0KDQojIFNlc3Npb24gSW5mbw0KYGBge3Igc2Vzc2lvbl9pbmZvLCBlY2hvID0gRkFMU0UsIHJlc3VsdHMgPSAnbWFya3VwJ30NCnNlc3Npb25JbmZvKCkgICAgDQpgYGANCg0KPCEtLSBGb290ZXIgLS0+DQombmJzcDsNCjxociAvPg0KPHAgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPkEgd29yayBieSA8YSBocmVmPSJodHRwczovL2dpdGh1Yi5jb20vQ2xhdWRpdVBhcGFzdGVyaS8iPkNsYXVkaXUgUGFwYXN0ZXJpPC9hPjwvcD4NCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij48c3BhbiBzdHlsZT0iY29sb3I6ICM4MDgwODA7Ij48ZW0+Y2xhdWRpdS5wYXBhc3RlcmlAZ21haWwuY29tPC9lbT48L3NwYW4+PC9wPg0KJm5ic3A7DQo=